#include <bits/stdc++.h>
using namespace std;
struct node {
  int x;
  int y;
  int z;
  int t;
};
bool cmp(node a, node b) {
  if (a.x != b.x)
    return a.x < b.x;
  else {
    if (a.y != b.y)
      return a.y < b.y;
    else
      return a.z < b.z;
  }
}
vector<node> q;
bool used[50005];
int main() {
  int n;
  scanf("%d", &n);
  node a[50005];
  fill(used, used + 50005, 0);
  for (int i = 1; i <= n; ++i) {
    scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
    a[i].t = i;
  }
  sort(a + 1, a + n + 1, cmp);
  for (int i = 1; i < n; ++i) {
    if (a[i].x == a[i + 1].x && a[i].y == a[i + 1].y) {
      printf("%d %d\n", a[i].t, a[i + 1].t);
      used[i] = 1;
      used[i + 1] = 1;
      ++i;
    }
  }
  for (int i = 1; i <= n; i++) {
    if (used[i] == 0) {
      q.push_back(a[i]);
    }
  }
  fill(used, used + 50005, 0);
  for (int i = 0; i < q.size(); ++i) {
    if (q[i].x == q[i + 1].x) {
      printf("%d %d\n", q[i].t, q[i + 1].t);
      used[i] = 1;
      used[i + 1] = 1;
      ++i;
    }
  }
  int j = 0;
  for (int i = 0; i < q.size(); ++i) {
    if (used[i] == 0) {
      a[j++] = q[i];
    }
  }
  for (int i = 0; i < j; i = i + 2) {
    printf("%d %d\n", a[i].t, a[i + 1].t);
  }
  return 0;
}
