import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            // StringBuffer sb1=new StringBuffer();
            // if(n==100)
            // {
            // sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            // sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            // sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
            //  System.out.println(sb1);
            // }
            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(!ts.contains(i))
                   continue;
                  ts.remove(i);
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        // bb[i]=true;
                        // bb[u]=true;
                        //ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        // bb[i]=true;
                        // bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        // bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              if(!ts.contains(j))
                               continue;
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                              if(n==100 && a[i][3]==22 && (a[j][3]==71 || a[j][3]==38))
                               System.out.println(d+" "+a[j][2]+" "+a[u][3]);
                        }
                        // bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            StringBuffer sb1=new StringBuffer();
            if(n==100)
            {
            sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]);
            sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]);
            sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]);
             System.out.println(sb1);
            }
            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        bb[i]=true;
                        bb[u]=true;
                        ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        bb[i]=true;
                        bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            long a[][]=new long[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=(long)Integer.parseInt(s1[0]);
                  a[i][1]=(long)Integer.parseInt(s1[1]);
                  a[i][2]=(long)Integer.parseInt(s1[2]);
                  a[i][3]=(long)i+1;
            }

            // StringBuffer sb1=new StringBuffer();
            // if(n==100)
            // {
            // sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            // sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            // sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
            //  System.out.println(sb1);
            // }
            Arrays.sort(a,new Comparator<long[]>(){
                  public int compare(final long f1[],final long f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(!ts.contains(i))
                   continue;
                  ts.remove(i);
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        // bb[i]=true;
                        // bb[u]=true;
                        //ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][0]==a[u][0];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        // bb[i]=true;
                        // bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        // bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              if(!ts.contains(j))
                               continue;
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                              // if(n==100 && a[i][3]==22 && (a[j][3]==71 || a[j][3]==38))
                              //  System.out.println(d+" "+a[j][2]+" "+a[u][3]);
                        }
                        // bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            long a[][]=new long[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=(long)Integer.parseInt(s1[0]);
                  a[i][1]=(long)Integer.parseInt(s1[1]);
                  a[i][2]=(long)Integer.parseInt(s1[2]);
                  a[i][3]=(long)i+1;
            }

            // StringBuffer sb1=new StringBuffer();
            // if(n==100)
            // {
            // sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            // sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            // sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
            //  System.out.println(sb1);
            // }
            Arrays.sort(a,new Comparator<long[]>(){
                  public int compare(final long f1[],final long f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(!ts.contains(i))
                   continue;
                  ts.remove(i);
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        // bb[i]=true;
                        // bb[u]=true;
                        //ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        // bb[i]=true;
                        // bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        // bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              if(!ts.contains(j))
                               continue;
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                              // if(n==100 && a[i][3]==22 && (a[j][3]==71 || a[j][3]==38))
                              //  System.out.println(d+" "+a[j][2]+" "+a[u][3]);
                        }
                        // bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            // StringBuffer sb1=new StringBuffer();
            // if(n==100)
            // {
            // sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            // sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            // sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
            //  System.out.println(sb1);
            // }
            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(!ts.contains(i))
                   continue;
                  ts.remove(i);
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        // bb[i]=true;
                        // bb[u]=true;
                        //ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        // bb[i]=true;
                        // bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        // bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              if(!ts.contains(j))
                               continue;
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        // bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            // StringBuffer sb1=new StringBuffer();
            // if(n==100)
            // {
            // sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            // sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            // sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
            //  System.out.println(sb1);
            // }
            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        bb[i]=true;
                        bb[u]=true;
                        ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        bb[i]=true;
                        bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=i+1;
                        for(int j=i+1;j<n && a[j][2]==a[u][2];j++)
                        {
                              if(!ts.contains(j))
                               continue;
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            int x[]=new int[n];
            int y[]=new int[n];

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  if(a[i][2]==a[i+1][2])
                  {
                        bb[i]=true;
                        bb[i+1]=true;
                        sb.append(a[i][3]).append(" ").append(a[i+1][3]).append("\n");
                  }
                  else
                  {
                        bb[i]=true;
                        // int l=i+1,r=n-1;
                        // while(r-l>1)
                        // {
                        //       int mid=(l+r)/2;
                        //       if(a[mid][0]==a[i+1][0])
                        //        l=mid;
                        //       else
                        //        r=mid;
                        // }

                        // if(a[r][0]==a[i+1][0])
                        //  l=r;

                        long min=Long.MAX_VALUE;
                        int pos=i+1;
                        for(int j=i+1;j<n && a[j][2]==a[i+1][2];j++)
                        {
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]) + (a[i][2]-a[j][2])*(a[i][2]-a[j][2]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            // StringBuffer sb1=new StringBuffer();
            // if(n==100)
            // {
            // sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            // sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            // sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
            //  System.out.println(sb1);
            // }
            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  ts.remove(i);
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        // bb[i]=true;
                        // bb[u]=true;
                        //ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        // bb[i]=true;
                        // bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        // bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              if(!ts.contains(j))
                               continue;
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        // bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        //ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            StringBuffer sb1=new StringBuffer();
            if(n==100)
            {
            sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]).append("\n");
            sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]).append("\n");
            sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]).append("\n");
             System.out.println(sb1);
            }
            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        bb[i]=true;
                        bb[u]=true;
                        ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        bb[i]=true;
                        bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            int x[]=new int[n];
            int y[]=new int[n];

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        bb[i]=true;
                        bb[u]=true;
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        bb[i]=true;
                        bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                  }
                  else
                  {
                        bb[i]=true;
                        // int l=i+1,r=n-1;
                        // while(r-l>1)
                        // {
                        //       int mid=(l+r)/2;
                        //       if(a[mid][0]==a[i+1][0])
                        //        l=mid;
                        //       else
                        //        r=mid;
                        // }

                        // if(a[r][0]==a[i+1][0])
                        //  l=r;

                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            StringBuffer sb1=new StringBuffer();
            sb1.append(a[21][0]+" "+a[21][1]+" "+a[21][2]);
            sb1.append(a[70][0]+" "+a[70][1]+" "+a[70][2]);
            sb1.append(a[37][0]+" "+a[37][1]+" "+a[37][2]);
            if(n==10)
             System.out.println(sb1);

            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        bb[i]=true;
                        bb[u]=true;
                        ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        bb[i]=true;
                        bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        bb[i]=true;
                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.util.*;
import java.io.*;

public class A
{
      public static void main(String ar[]) throws Exception
      {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int n=Integer.parseInt(br.readLine());
            int a[][]=new int[n][4];
            for(int i=0;i<n;i++)
            {
                  String s1[]=br.readLine().split(" ");
                  a[i][0]=Integer.parseInt(s1[0]);
                  a[i][1]=Integer.parseInt(s1[1]);
                  a[i][2]=Integer.parseInt(s1[2]);
                  a[i][3]=i+1;
            }

            Arrays.sort(a,new Comparator<int[]>(){
                  public int compare(final int f1[],final int f2[]){
                        if(f1[2]>f2[2])
                         return 1;
                        else if(f1[2]==f2[2])
                        {
                           if(f1[0]>f2[0])
                            return 1;
                           else if(f1[0]==f2[0])
                            return ((f1[1]>f2[1])?1:-1);
                           else
                            return -1;
                        }
                        else
                         return -1;
                  }
            });

            int x[]=new int[n];
            int y[]=new int[n];

            StringBuffer sb=new StringBuffer();
            boolean bb[]=new boolean[n];
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<n;i++)
             ts.add(i);
            for(int i=0;i<n-1;i++)
            {
                  if(bb[i])
                   continue;
                  int u=ts.higher(i);
                  if(a[i][2]==a[u][2] && a[i][0]==a[u][0])
                  {
                        bb[i]=true;
                        bb[u]=true;
                        ts.remove(i);
                        ts.remove(u);
                        sb.append(a[i][3]).append(" ").append(a[u][3]).append("\n");
                  }
                  else if(a[i][2]==a[u][2])
                  {
                        long min=Long.MAX_VALUE;
                        int pp=u;
                        for(int j=u;j<n && a[j][2]==a[u][2] && a[j][2]==a[u][2];j++)
                        {
                              if(ts.contains(j) && min>Math.abs(a[j][1]-a[i][1]))
                              { min=Math.abs(a[j][1]-a[i][1]); pp=j; }
                        }
                        bb[i]=true;
                        bb[pp]=true;
                        sb.append(a[i][3]).append(" ").append(a[pp][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pp);
                  }
                  else
                  {
                        bb[i]=true;
                        // int l=i+1,r=n-1;
                        // while(r-l>1)
                        // {
                        //       int mid=(l+r)/2;
                        //       if(a[mid][0]==a[i+1][0])
                        //        l=mid;
                        //       else
                        //        r=mid;
                        // }

                        // if(a[r][0]==a[i+1][0])
                        //  l=r;

                        long min=Long.MAX_VALUE;
                        int pos=u;
                        for(int j=u;j<n && a[j][2]==a[u][2];j++)
                        {
                              long d=(a[i][0]-a[j][0])*(a[i][0]-a[j][0]) + (a[i][1]-a[j][1])*(a[i][1]-a[j][1]);
                              if(d<min)
                              { min=d; pos=j; }
                        }
                        bb[pos]=true;
                        sb.append(a[i][3]).append(" ").append(a[pos][3]).append("\n");
                        ts.remove(i);
                        ts.remove(pos);
                  }
            }

            System.out.println(sb);
      }
}


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class CF {
	static class Point implements Comparable<Point>{
		public long x,y,z;
		public int idx;
		Point(){}
		Point(int id,long xx,long yy,long zz){
			idx=id;x=xx;y=yy;z=zz;
		}
		@Override
		public int compareTo(Point other) {
			if(x!=other.x) return (int) (x-other.x);
			else if(y!=other.y)return (int)(y-other.y);
			else return (int)(z-other.z);
		}
		@Override
		public String toString() {
			return Integer.toString(idx)+";"+Long.toString(x)+";"+Long.toString(y)+";"
			+Long.toString(z);
		}
	}
	static class KComparator implements Comparator<Point>{

		@Override
		public int compare(Point o1, Point o2) {
			if(o1.x!=o2.x)return (int)(o1.x-o2.x);
			else if(o1.y!=o2.y)return (int)(o1.y-o2.y);
			else return (int)(o1.z-o2.z);
		}

	}
	public static void main(String[] args) throws FileNotFoundException {
//		InputStream stream=new FileInputStream("in.txt");
		InputReader reader=new InputReader(System.in);
		int n=Integer.parseInt(reader.next());
		Point pArrayList[]=new Point[n];
		boolean vis[]=new boolean[n+10];
		for(int ii=0;ii<n;ii++) {
			pArrayList[ii]=new Point();
			pArrayList[ii].idx=ii+1;
			pArrayList[ii].x=Integer.parseInt(reader.next());
			pArrayList[ii].y=Integer.parseInt(reader.next());
			pArrayList[ii].z=Integer.parseInt(reader.next());
		}
		Arrays.sort(pArrayList,new KComparator());
		int l=0;
		for(int ii=1;ii<n;ii++) {
			if(l!=-1&&pArrayList[l].x==pArrayList[ii].x
					&&pArrayList[l].y==pArrayList[ii].y) {
				System.out.println(pArrayList[l].idx+" "+pArrayList[ii].idx);
				vis[l]=vis[ii]=true;
				l=-1;
			}
			else l=ii;
		}
		l=0;while(vis[l])l++;
		for(int ii=l+1;ii<n;ii++) {
			if(vis[ii])continue;
			if(l!=-1&&pArrayList[l].x==pArrayList[ii].x) {
					System.out.println(pArrayList[l].idx+" "+pArrayList[ii].idx);
					vis[l]=vis[ii]=true;
					l=-1;
			}
			else l=ii;
		}
		l=0;while(vis[l])l++;
		for(int ii=l+1;ii<n;ii++) {
			if(vis[ii])continue;
			if(l!=-1) {
				System.out.println(pArrayList[l].idx+" "+pArrayList[ii].idx);
				vis[l]=vis[ii]=true;
				l=-1;
			}
			else l=ii;
		}
	}
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
    }
}


import java.util.*;
import java.io.*;
public class Main{
    static PrintWriter out;
    static InputReader in;
    public static void main(String args[]){
        out = new PrintWriter(System.out);
        in = new InputReader();
        new Main();
        out.flush(); out.close();
    }
    Main(){
        solve();
    }
    class pair{
        int F, S, T, I;
        pair(int a, int b, int c, int d){
            F = a; S = b; T = c; I = d;
        }
    }
    ArrayList<pair> al = new ArrayList<>();
    void solve(){
        int n = in.nextInt();
        for(int i = 0; i < n; i++){
            al.add(new pair(in.nextInt(), in.nextInt(), in.nextInt(), i + 1));
        }
        Collections.sort(al, (A, B) -> A.F == B.F ? A.S == B.S ? A.T - B.T : A.S - B.S : A.F - B.F);
        for(int i = 0; i < n; i += 2){
            out.println(al.get(i).I + " " + al.get(i + 1).I);
        }
    }
    public static class InputReader{
        BufferedReader br;
        StringTokenizer st;
        InputReader(){
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        public int nextInt(){
            return Integer.parseInt(next());
        }
        public long nextLong(){
            return Long.parseLong(next());
        }
        public double nextDouble(){
            return Double.parseDouble(next());
        }
        public String next(){
            while(st == null || !st.hasMoreTokens()){
                try{
                    st = new StringTokenizer(br.readLine());
                }catch(IOException e){}
            }
            return st.nextToken();
        }
    }
}


import java.util.*;
import java.io.*;
public class Main{
    static PrintWriter out;
    static InputReader in;
    public static void main(String args[]){
        out = new PrintWriter(System.out);
        in = new InputReader();
        new Main();
        out.flush(); out.close();
    }
    Main(){
        solve();
    }
    class pair{
        long F, S, T; int I;
        pair(long a, long b, long c, int d){
            F = a; S = b; T = c; I = d;
        }
    }
    ArrayList<pair> al = new ArrayList<>();
    void solve(){
        int n = in.nextInt();
        boolean cons[] = new boolean[n + 1];
        for(int i = 0; i < n; i++)al.add(new pair(in.nextInt(), in.nextInt(), in.nextInt(), i + 1));
        ArrayList<pair> xy = new ArrayList<>();
        for(int i = 0; i < n; i++){
            pair p = al.get(i);
            xy.add(new pair(p.F * (long)1e10 + p.S, p.T, -1, p.I));
        }
        Collections.sort(xy, (A, B) -> A.F == B.F ? Long.compare(A.S, B.S) : Long.compare(A.F, B.F));
        for(int i = 0; i < n - 1; ){
            pair p1 = xy.get(i), p2 = xy.get(i + 1);
            if(p1.F == p2.F){
                out.println(p1.I + " " + p2.I);
                cons[p1.I] = cons[p2.I] = true;
                i += 2;
            }else{
                i++;
            }
        }
        ArrayList<pair> x = new ArrayList<>();
        for(int i = 0; i < n; i++){
            pair p = al.get(i);
            if(cons[p.I])continue;
            x.add(p);
        }
        Collections.sort(x, (A, B) -> A.F == B.F ? Long.compare(A.S, B.S) : Long.compare(A.F, B.F));
        for(int i = 0; i < x.size() - 1;){
            pair p1 = x.get(i), p2 = x.get(i + 1);
            if(p1.F == p2.F){
                out.println(p1.I + " " + p2.I);
                cons[p1.I] = cons[p2.I] = true;
                i += 2;
            }else i++;
        }
        ArrayList<pair> a = new ArrayList<>();
        for(int i = 0; i < x.size(); i++){
            pair p = x.get(i);
            if(cons[p.I])continue;
            a.add(p);
        }
        Collections.sort(a, (A, B) -> A.F == B.F ? A.S == B.S ? Long.compare(A.T, B.T) : Long.compare(A.S, B.S) : Long.compare(A.F, B.F));
        for(int i = 0; i < a.size() - 1; i += 2){
            pair p1 = a.get(i), p2 = a.get(i + 1);
            out.println(p1.I + " " + p2.I);
        }
    }
    public static class InputReader{
        BufferedReader br;
        StringTokenizer st;
        InputReader(){
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        public int nextInt(){
            return Integer.parseInt(next());
        }
        public long nextLong(){
            return Long.parseLong(next());
        }
        public double nextDouble(){
            return Double.parseDouble(next());
        }
        public String next(){
            while(st == null || !st.hasMoreTokens()){
                try{
                    st = new StringTokenizer(br.readLine());
                }catch(IOException e){}
            }
            return st.nextToken();
        }
    }
}


import java.io.*;
import java.util.*;

public class A {
    FastScanner in;
    PrintWriter out;

    void solve() {
        int n = in.nextInt();
        Point[] a = new Point[n];
        for (int i = 0; i < n; i++) {
            a[i] = new Point(in.nextInt(), in.nextInt(), in.nextInt(), i + 1);
        }
        Arrays.sort(a);
        recX(a);
    }

    void recX(Point[] a) {
        List<Point> next = new ArrayList<>();
        for (int i = 0; i < a.length; ) {
            int j = i;
            while (j != a.length && a[i].x == a[j].x) {
                j++;
            }
            Point t = recY(a, i, j);
            if (t != null) {
                next.add(t);
            }
            i = j;
        }
        makePairs(next);
    }

    Point recY(Point[] a, int from, int to) {
        List<Point> next = new ArrayList<>();
        for (int i = from; i < to; ) {
            int j = i;
            while (j != to && a[i].y == a[j].y) {
                j++;
            }
            Point t = recZ(a, i, j);
            if (t != null) {
                next.add(t);
            }
            i = j;
        }
        return makePairs(next);
    }

    Point recZ(Point[] a, int from, int to) {
        List<Point> next = new ArrayList<>();
        for (int i = from; i < to; i++) {
            next.add(a[i]);
        }
        return makePairs(next);
    }

    Point makePairs(List<Point> a) {
        for (int i = 0; i + 1 < a.size(); i += 2) {
            out.println(a.get(i).id + " " + a.get(i + 1).id);
        }
        if (a.size() % 2 == 1) {
            return a.get(a.size() - 1);
        }
        return null;
    }

    class Point implements Comparable<Point> {
        int x, y, z;

        int id;

        public Point(int x, int y, int z, int id) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.id = id;
        }

        @Override
        public int compareTo(Point o) {
            if (x != o.x) {
                return Integer.compare(x, o.x);
            }
            if (y != o.y) {
                return Integer.compare(y, o.y);
            }
            return Integer.compare(z, o.z);
        }
    }

    void run() {
        try {
            in = new FastScanner(new File("A.in"));
            out = new PrintWriter(new File("A.out"));

            solve();

            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    void runIO() {

        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner(InputStream f) {
            br = new BufferedReader(new InputStreamReader(f));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }
    }

    public static void main(String[] args) {
        new A().runIO();
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Objects;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.Comparator;
import java.util.Collections;
import java.io.InputStream;

/**
 * Built using CHelper plug-in Actual solution is at the top
 *
 * @author ilyakor
 */
public class Main {

  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    InputReader in = new InputReader(inputStream);
    OutputWriter out = new OutputWriter(outputStream);
    TaskC1 solver = new TaskC1();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskC1 {

    OutputWriter out;
    HashSet<TaskC1.Point> alive;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
      this.out = out;

      alive = new HashSet<>();
      int n = in.nextInt();
      ArrayList<TaskC1.Point> a = new ArrayList<>();
      for (int i = 0; i < n; ++i) {
        TaskC1.Point p = new TaskC1.Point(in.nextInt(), in.nextInt(), in.nextInt(), i + 1);
        a.add(p);
        // alive.add(p);
      }
      solveX(a);
    }

    void print(TaskC1.Point p1, TaskC1.Point p2) {
      out.printLine(p1.id + " " + p2.id);
      // alive.remove(p1);
      // alive.remove(p2);
      // for (Point p : alive) {
      //     if (bad(p.x, p1.x, p2.x) && bad(p.y, p1.y, p2.y) && bad(p.z, p1.z, p2.z))
      //         throw new RuntimeException();
      // }
    }

    void solveX(ArrayList<TaskC1.Point> a) {
      Collections.sort(a, new Comparator<TaskC1.Point>() {

        public int compare(TaskC1.Point p1, TaskC1.Point p2) {
          if (p1.x != p2.x) {
            return Integer.compare(p1.x, p2.x);
          }
          if (p1.y != p2.y) {
            return Integer.compare(p1.y, p2.y);
          }
          if (p1.z != p2.z) {
            return Integer.compare(p1.z, p2.z);
          }
          return 0;
        }
      });
      ArrayList<TaskC1.Point> remaining = new ArrayList<>();
      ArrayList<TaskC1.Point> cur = new ArrayList<>();
      cur.add(a.get(0));
      for (int i = 1; i < a.size(); ++i) {
        if (cur.get(0).x != a.get(i).x) {
          cur = solveY(cur);
          remaining.addAll(cur);
          cur.clear();
          cur.add(a.get(i));
        } else {
          cur.add(a.get(i));
        }
      }
      cur = solveY(cur);
      remaining.addAll(cur);
      if (remaining.size() % 2 != 0) {
        throw new RuntimeException();
      }
      for (int i = 0; i < remaining.size(); i += 2) {
        print(remaining.get(i), remaining.get(i + 1));
      }
    }

    ArrayList<TaskC1.Point> solveY(ArrayList<TaskC1.Point> a) {
      Collections.sort(a, new Comparator<TaskC1.Point>() {

        public int compare(TaskC1.Point p1, TaskC1.Point p2) {
          if (p1.y != p2.y) {
            return Integer.compare(p1.y, p2.y);
          }
          if (p1.z != p2.z) {
            return Integer.compare(p1.z, p2.z);
          }
          if (p1.x != p2.x) {
            return Integer.compare(p1.x, p2.x);
          }
          return 0;
        }
      });
      ArrayList<TaskC1.Point> remaining = new ArrayList<>();
      ArrayList<TaskC1.Point> cur = new ArrayList<>();
      cur.add(a.get(0));
      for (int i = 1; i < a.size(); ++i) {
        if (cur.get(0).y != a.get(i).y) {
          cur = solveZ(cur);
          remaining.addAll(cur);
          cur.clear();
          cur.add(a.get(i));
        } else {
          cur.add(a.get(i));
        }
      }
      cur = solveZ(cur);
      remaining.addAll(cur);
      for (int i = 0; i + 1 < remaining.size(); i += 2) {
        print(remaining.get(i), remaining.get(i + 1));
      }
      ArrayList<TaskC1.Point> res = new ArrayList<>();
      if (remaining.size() % 2 == 1) {
        res.add(remaining.get(remaining.size() - 1));
      }
      return res;
    }

    ArrayList<TaskC1.Point> solveZ(ArrayList<TaskC1.Point> a) {
      Collections.sort(a, new Comparator<TaskC1.Point>() {

        public int compare(TaskC1.Point p1, TaskC1.Point p2) {
          if (p1.z != p2.z) {
            return Integer.compare(p1.z, p2.z);
          }
          if (p1.x != p2.x) {
            return Integer.compare(p1.x, p2.x);
          }
          if (p1.y != p2.y) {
            return Integer.compare(p1.y, p2.y);
          }
          return 0;
        }
      });
      for (int i = 0; i + 1 < a.size(); i += 2) {
        print(a.get(i), a.get(i + 1));
      }
      ArrayList<TaskC1.Point> res = new ArrayList<>();
      if (a.size() % 2 == 1) {
        res.add(a.get(a.size() - 1));
      }
      return res;
    }

    static class Point {

      int x;
      int y;
      int z;
      int id;

      public Point(int x, int y, int z, int id) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.id = id;
      }

      public boolean equals(Object o) {
        if (this == o) {
          return true;
        }
        if (!(o instanceof TaskC1.Point)) {
          return false;
        }
        TaskC1.Point point = (TaskC1.Point) o;
        return x == point.x &&
            y == point.y &&
            z == point.z &&
            id == point.id;
      }

      public int hashCode() {
        return Objects.hash(x, y, z, id);
      }

    }

  }

  static class OutputWriter {

    private final PrintWriter writer;

    public OutputWriter(OutputStream outputStream) {
      writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public OutputWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void print(Object... objects) {
      for (int i = 0; i < objects.length; i++) {
        if (i != 0) {
          writer.print(' ');
        }
        writer.print(objects[i]);
      }
    }

    public void printLine(Object... objects) {
      print(objects);
      writer.println();
    }

    public void close() {
      writer.close();
    }

  }

  static class InputReader {

    private InputStream stream;
    private byte[] buffer = new byte[10000];
    private int cur;
    private int count;

    public InputReader(InputStream stream) {
      this.stream = stream;
    }

    public static boolean isSpace(int c) {
      return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public int read() {
      if (count == -1) {
        throw new InputMismatchException();
      }
      try {
        if (cur >= count) {
          cur = 0;
          count = stream.read(buffer);
          if (count <= 0) {
            return -1;
          }
        }
      } catch (IOException e) {
        throw new InputMismatchException();
      }
      return buffer[cur++];
    }

    public int readSkipSpace() {
      int c;
      do {
        c = read();
      } while (isSpace(c));
      return c;
    }

    public int nextInt() {
      int sgn = 1;
      int c = readSkipSpace();
      if (c == '-') {
        sgn = -1;
        c = read();
      }
      int res = 0;
      do {
        if (c < '0' || c > '9') {
          throw new InputMismatchException();
        }
        res = res * 10 + c - '0';
        c = read();
      } while (!isSpace(c));
      res *= sgn;
      return res;
    }

  }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class Solution{

	static PrintWriter out = new PrintWriter(System.out);
	static int n;
	static int[][] arr;

    public static void main(String[] args) throws IOException {

    	FastScanner fs = new FastScanner();
//    	PrintWriter out = new PrintWriter(System.out);

    	int tt = 1;
    	while(tt-->0) {

    		n = fs.nextInt();
    		arr = new int[n][3];

    		for(int i=0;i<n;i++) {
    			arr[i][0] = fs.nextInt();
    			arr[i][1] = fs.nextInt();
    			arr[i][2] = fs.nextInt();
    		}

    		ArrayList<Integer> p = new ArrayList<Integer>();
    		for(int i=0;i<n;i++) p.add(i);

    		solve(p, 0);

    	}

    	out.close();

    }

    //It returns the pt. left or -1 if no point is left
    static int solve(ArrayList<Integer> p, int k) {
    	int sz = p.size();
    	if(sz==1) return p.get(0);

    	//the pt which will be left or -1
    	int w = -1;

    	TreeMap<Integer, ArrayList<Integer>> map = new TreeMap<Integer, ArrayList<Integer>>();
    	for(int i: p) {
    		if(!map.containsKey(arr[i][k])) map.put(arr[i][k], new ArrayList<Integer>());
    		map.get(arr[i][k]).add(i);
    	}

    	for(int i: map.keySet()) {
    		ArrayList<Integer> l = map.get(i);
    		int pt = solve(l, k+1);
    		if(pt==-1) continue;
    		if(w==-1) {
    			w = pt;
    		}
    		else {
    			out.println(w+1+" "+(pt+1));
    			w = -1;
    		}
    	}
    	return w;
    }

    static final Random random=new Random();

    static void ruffleSort(int[] a) {
    	int n=a.length;//shuffle, then sort
    	for (int i=0; i<n; i++) {
    		int oi=random.nextInt(n); int temp=a[oi];
    		a[oi]=a[i]; a[i]=temp;
    	}
    	Arrays.sort(a);
    }

    static class FastScanner{
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer st = new StringTokenizer("");

    	public String next(){
    		while(!st.hasMoreElements()){
    			try{
    				st = new StringTokenizer(br.readLine());
    			} catch(IOException e){
    				e.printStackTrace();
    			}
    		}
    		return st.nextToken();
    	}

    	public String nextLine() throws IOException {
    		return br.readLine();
    	}

    	public int nextInt(){
    		return Integer.parseInt(next());
    	}

    	public int[] readArray(int n){
    		int[] a = new int[n];
    		for(int i=0;i<n;i++)
    			a[i] = nextInt();
    		return a;
    	}

    	public long nextLong() {
    		return Long.parseLong(next());
    	}

    	public char nextChar() {
    		return next().toCharArray()[0];
    	}
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Stack;
import java.util.StringTokenizer;

public class ProblemC {
    static class Point implements Comparable<Point> {
        int i, x, y, z;

        public Point(int i, int x, int y, int z) {
            this.i = i + 1;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public int compareTo(Point p) {
            int xDiff = Integer.compare(x, p.x);
            int yDiff = Integer.compare(y, p.y);
            int zDiff = Integer.compare(z, p.z);
            if (xDiff != 0) return xDiff;
            if (yDiff != 0) return yDiff;
            return zDiff;
        }

        boolean isBetween(Point a, Point b) {
            return x >= Math.min(a.x, b.x)
                    && x <= Math.max(a.x, b.x)
                    && y >= Math.min(a.y, b.y)
                    && y <= Math.max(a.y, b.y)
                    && z >= Math.min(a.z, b.z)
                    && z <= Math.max(a.z, b.z);
        }

        @Override
        public String toString() {
            return "Point{" +
                "i=" + i +
                ", x=" + x +
                ", y=" + y +
                ", z=" + z +
                '}';
        }
    }

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        InputReader in = new InputReader(inputStream);
        int n = in.nextInt();
        LinkedList<Point> points = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }
        Collections.sort(points);
        Stack<Point> s = new Stack<>();

        while (!s.isEmpty() || !points.isEmpty()) {
            Point a = s.isEmpty()? points.removeFirst() : s.pop();
            Point b = s.isEmpty()? points.removeFirst() : s.pop();
            Iterator<Point> i = points.iterator();
            boolean canDelete = true;
            while (i.hasNext()) {
                Point m = i.next();
                if (m.isBetween(a, b)) {
                    s.push(b);
                    s.push(m);
                    s.push(a);
                    i.remove();
                    canDelete = false;
                    break;
                }
            }
            if (canDelete) {
                System.out.println(a.i + " "+ b.i);
            }
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class ProblemC {
    static class Point implements Comparable<Point> {
        int i, x, y, z;

        public Point(int i, int x, int y, int z) {
            this.i = i + 1;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public int compareTo(Point p) {
            int xDiff = Integer.compare(x, p.x);
            int yDiff = Integer.compare(y, p.y);
            int zDiff = Integer.compare(z, p.z);
            if (xDiff != 0) return xDiff;
            if (yDiff != 0) return yDiff;
            return zDiff;
        }

        boolean isBetween(Point a, Point b) {
            return x >= Math.min(a.x, b.x)
                    && x <= Math.max(a.x, b.x)
                    && y >= Math.min(a.y, b.y)
                    && y <= Math.max(a.y, b.y)
                    && z >= Math.min(a.z, b.z)
                    && z <= Math.max(a.z, b.z);
        }

        @Override
        public String toString() {
            return "Point{" +
                "i=" + i +
                ", x=" + x +
                ", y=" + y +
                ", z=" + z +
                '}';
        }
    }

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        InputReader in = new InputReader(inputStream);
        int n = in.nextInt();
        List<Point> points = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }
        Collections.sort(points);
        boolean x = false, y = false;
        for (int i = 0; i < points.size(); i+=2) {
            if ((x || points.get(i).x == points.get(i+1).x) && (y || points.get(i).y == points.get(i+1).y)) {
                System.out.println(points.get(i).i + " " + points.get(i+1).i);
                points.set(i, null); points.set(i+1, null);
            }
        }
        y = true;
        points = points.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Collections.sort(points);
        for (int i = 0; i < points.size(); i+=2) {
            if ((x || points.get(i).x == points.get(i+1).x) && (y || points.get(i).y == points.get(i+1).y)) {
                System.out.println(points.get(i).i + " " + points.get(i+1).i);
                points.set(i, null); points.set(i+1, null);
            }
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class ProblemC {
    static class Point implements Comparable<Point> {
        int i, x, y, z;

        public Point(int i, int x, int y, int z) {
            this.i = i + 1;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public int compareTo(Point p) {
            int xDiff = Integer.compare(x, p.x);
            int yDiff = Integer.compare(y, p.y);
            int zDiff = Integer.compare(z, p.z);
            if (xDiff != 0) return xDiff;
            if (yDiff != 0) return yDiff;
            return zDiff;
        }

        boolean isBetween(Point a, Point b) {
            return x >= Math.min(a.x, b.x)
                    && x <= Math.max(a.x, b.x)
                    && y >= Math.min(a.y, b.y)
                    && y <= Math.max(a.y, b.y)
                    && z >= Math.min(a.z, b.z)
                    && z <= Math.max(a.z, b.z);
        }

        @Override
        public String toString() {
            return "Point{" + "i=" + i + ", x=" + x + ", y=" + y + ", z=" + z + '}';
        }
    }

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        InputReader in = new InputReader(inputStream);
        int n = in.nextInt();
        List<Point> points = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }
        Collections.sort(points);
        for (int i = 0; i < points.size(); i += 2) {
            if (points.get(i).x == points.get(i + 1).x && points.get(i).y == points.get(i + 1).y) {
                System.out.println(points.get(i).i + " " + points.get(i + 1).i);
                points.set(i, null);
                points.set(i + 1, null);
            }
        }
        points = points.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Collections.sort(points);
        for (int i = 0; i < points.size(); i += 2) {
            if (points.get(i).x == points.get(i + 1).x) {
                System.out.println(points.get(i).i + " " + points.get(i + 1).i);
                points.set(i, null);
                points.set(i + 1, null);
            }
        }
        points = points.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Collections.sort(points);
        for (int i = 0; i < points.size(); i += 2) {
            System.out.println(points.get(i).i + " " + points.get(i + 1).i);
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class ProblemC {
    static class Point implements Comparable<Point> {
        int i, x, y, z;

        public Point(int i, int x, int y, int z) {
            this.i = i + 1;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public int compareTo(Point p) {
            int xDiff = Integer.compare(x, p.x);
            int yDiff = Integer.compare(y, p.y);
            int zDiff = Integer.compare(z, p.z);
            if (xDiff != 0) return xDiff;
            if (yDiff != 0) return yDiff;
            return zDiff;
        }

        boolean isBetween(Point a, Point b) {
            return x >= Math.min(a.x, b.x)
                    && x <= Math.max(a.x, b.x)
                    && y >= Math.min(a.y, b.y)
                    && y <= Math.max(a.y, b.y)
                    && z >= Math.min(a.z, b.z)
                    && z <= Math.max(a.z, b.z);
        }

        @Override
        public String toString() {
            return "Point{" + "i=" + i + ", x=" + x + ", y=" + y + ", z=" + z + '}';
        }
    }

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        InputReader in = new InputReader(inputStream);
        int n = in.nextInt();
        List<Point> points = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }
        Collections.sort(points);
        for (int i = 0; i < points.size()-1; i++) {
            if (points.get(i) != null && points.get(i).x == points.get(i + 1).x && points.get(i).y == points.get(i + 1).y) {
                System.out.println(points.get(i).i + " " + points.get(i + 1).i);
                points.set(i, null);
                points.set(i + 1, null);
            }
        }
        points = points.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Collections.sort(points);
        for (int i = 0; i < points.size()-1; i++) {
            if (points.get(i) != null && points.get(i).x == points.get(i + 1).x) {
                System.out.println(points.get(i).i + " " + points.get(i + 1).i);
                points.set(i, null);
                points.set(i + 1, null);
            }
        }
        points = points.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Collections.sort(points);
        for (int i = 0; i < points.size(); i += 2) {
            System.out.println(points.get(i).i + " " + points.get(i + 1).i);
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.Stack;
    import java.util.StringTokenizer;

    public class ProblemC {
        static class Point implements Comparable<Point> {
            int i, x, y, z;

            public Point(int i, int x, int y, int z) {
                this.i = i + 1;
                this.x = x;
                this.y = y;
                this.z = z;
            }

            @Override
            public int compareTo(Point p) {
                int xDiff = Integer.compare(x, p.x);
                int yDiff = Integer.compare(y, p.y);
                int zDiff = Integer.compare(z, p.z);
                if (xDiff != 0) return xDiff;
                if (yDiff != 0) return yDiff;
                return zDiff;
            }

            boolean isBetween(Point a, Point b) {
                return x >= Math.min(a.x, b.x)
                        && x <= Math.max(a.x, b.x)
                        && y >= Math.min(a.y, b.y)
                        && y <= Math.max(a.y, b.y)
                        && z >= Math.min(a.z, b.z)
                        && z <= Math.max(a.z, b.z);
            }

            @Override
            public String toString() {
                return "Point{" +
                    "i=" + i +
                    ", x=" + x +
                    ", y=" + y +
                    ", z=" + z +
                    '}';
            }
        }

        public static void main(String[] args) {
            InputStream inputStream = System.in;
            InputReader in = new InputReader(inputStream);
            int n = in.nextInt();
            LinkedList<Point> points = new LinkedList<>();
            for (int i = 0; i < n; i++) {
                points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
            }
            Stack<Point> s = new Stack<>();

            while (!s.isEmpty() || !points.isEmpty()) {
                Point a = s.isEmpty()? points.removeFirst() : s.pop();
                Point b = s.isEmpty()? points.removeFirst() : s.pop();
                Iterator<Point> i = points.iterator();
                boolean canDelete = true;
                while (i.hasNext()) {
                    Point m = i.next();
                    if (m.isBetween(a, b)) {
                        s.push(b);
                        s.push(m);
                        s.push(a);
                        i.remove();
                        canDelete = false;
                        break;
                    }
                }
                if (canDelete) {
                    System.out.println(a.i + " "+ b.i);
                }
            }
        }

        static class InputReader {
            public BufferedReader reader;
            public StringTokenizer tokenizer;

            public InputReader(InputStream stream) {
                reader = new BufferedReader(new InputStreamReader(stream), 32768);
                tokenizer = null;
            }

            public String next() {
                while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                    try {
                        tokenizer = new StringTokenizer(reader.readLine());
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                return tokenizer.nextToken();
            }

            public int nextInt() {
                return Integer.parseInt(next());
            }

            public long nextLong() {
                return Long.parseLong(next());
            }

            public double nextDouble() {
                return Double.parseDouble(next());
            }
        }
    }


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class ProblemC {
    static class Point implements Comparable<Point> {
        int i, x, y, z;

        public Point(int i, int x, int y, int z) {
            this.i = i + 1;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public int compareTo(Point p) {
            int xDiff = Integer.compare(x, p.x);
            int yDiff = Integer.compare(y, p.y);
            int zDiff = Integer.compare(z, p.z);
            if (xDiff != 0) return xDiff;
            if (yDiff != 0) return yDiff;
            return zDiff;
        }

        boolean isBetween(Point a, Point b) {
            return x >= Math.min(a.x, b.x)
                    && x <= Math.max(a.x, b.x)
                    && y >= Math.min(a.y, b.y)
                    && y <= Math.max(a.y, b.y)
                    && z >= Math.min(a.z, b.z)
                    && z <= Math.max(a.z, b.z);
        }
    }

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        InputReader in = new InputReader(inputStream);
        int n = in.nextInt();
        List<Point> points = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }
        Collections.sort(points);
        boolean x = false, y = false;
        for (int i = 0; i < points.size(); i+=2) {
            if ((x || points.get(i).x == points.get(i).x) && (y || points.get(i).y == points.get(i).y)) {
                System.out.println(points.get(i).i + " " + points.get(i+1).i);
                points.set(i, null); points.set(i+1, null);
            }
        }
        y = true;
        points = points.stream().filter(Objects::nonNull).collect(Collectors.toList());
        for (int i = 0; i < points.size(); i+=2) {
            if ((x || points.get(i).x == points.get(i).x) && (y || points.get(i).y == points.get(i).y)) {
                System.out.println(points.get(i).i + " " + points.get(i+1).i);
                points.set(i, null); points.set(i+1, null);
            }
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Objects;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.Comparator;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        C2BalancedRemovalsHarder solver = new C2BalancedRemovalsHarder();
        solver.solve(1, in, out);
        out.close();
    }

    static class C2BalancedRemovalsHarder {
        private int n;
        private int[][] arr;
        private boolean[] flag;
        private static final int D = 3;
        private ArrayList<Util.Pair<Integer>> ans = new ArrayList<>();

        private void function(int from, int to, int dim) {
            if (dim == 1) {
                for (int i = from; i + 1 <= to; i += 2) {
                    ans.add(new Util.Pair<>(arr[i][0], arr[i + 1][0]));
                    flag[arr[i][0]] = flag[arr[i + 1][0]] = true;
                }
                return;
            }
            int num = arr[from][dim];
            int start = from, end = from;
            for (int i = from; i <= to; i++) {
                if (num == arr[i][dim]) end = i;
                else {
                    function(start, end, dim - 1);
                    num = arr[i][dim];
                    start = i;
                    end = i;
                }
            }
            function(start, end, dim - 1);
            ArrayList<Integer> temp = new ArrayList<>();
            for (int i = from; i <= to; i++) {
                if (!flag[arr[i][0]]) temp.add(arr[i][0]);
            }
            for (int i = 0; i + 1 < temp.size(); i += 2) {
                ans.add(new Util.Pair<>(temp.get(i), temp.get(i + 1)));
                flag[temp.get(i)] = flag[temp.get(i + 1)] = true;
            }
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            n = in.nextInt();
            flag = new boolean[n + 1];
            arr = new int[n + 1][D + 1];
            for (int i = 1; i <= n; i++) {
                arr[i][0] = i;
                for (int j = 1; j <= D; j++) arr[i][j] = in.nextInt();
            }
            Arrays.sort(arr, new Comparator<int[]>() {

                public int compare(int[] o1, int[] o2) {
                    for (int j = D; j >= 1; j--)
                        if (o1[j] != o2[j]) return o1[j] - o2[j];
                    return 0;
                }
            });
//        for (int i=0; i<arr.length; i++) out.println(Arrays.toString(arr[i]));
            function(1, n, D);
            for (int i = 0; i < ans.size(); i++) {
                out.printsc(ans.get(i).x, ans.get(i).y);
                out.println();
            }
            out.flush();
        }

    }

    static class Util {
        public static class Pair<T> {
            public T x;
            public T y;

            public Pair(T x, T y) {
                this.x = x;
                this.y = y;
            }

            public boolean equals(Object obj) {
                if (!(obj instanceof Util.Pair)) return false;
                Util.Pair<T> pair = (Util.Pair<T>) obj;
                return this.x.equals(pair.x) && this.y.equals(pair.y);
            }

            public String toString() {
                return ("(" + this.x + "," + this.y + ")");
            }

            public int hashCode() {
                return Objects.hash(x, y);
            }

        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[8192];
        private int curChar;
        private int numChars;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public InputReader(FileInputStream file) {
            this.stream = file;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res = (res << 3) + (res << 1) + c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;
        private ArrayList<String> res = new ArrayList<>();
        private StringBuilder sb = new StringBuilder("");

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                sb.append(objects[i]);
            }
            res.add(sb.toString());
            sb = new StringBuilder("");
        }

        public void printsc(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                sb.append(objects[i]).append(' ');
            }
        }

        public void close() {
            writer.close();
        }

        public void flush() {
            for (String str : res) writer.printf("%s\n", str);
            res.clear();
            sb = new StringBuilder("");
        }

    }
}