#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e4 + 10;
struct POINT {
  int x, y, z;
  int id;
  bool friend operator<(const POINT &a, const POINT &b) {
    if (a.y != b.y) return a.y < b.y;
    if (a.x != b.x) return a.x < b.x;
    return a.z < b.z;
  }
} p[MAXN], p2[MAXN], p3[MAXN];
bool vis[MAXN] = {0};
int main() {
  int N;
  scanf("%d", &N);
  for (int i = 1; i <= N; ++i) {
    scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].z);
    p[i].id = i;
  }
  sort(p + 1, p + 1 + N);
  int tot = 0;
  for (int i = 1; i <= N; ++i) {
    if (vis[p[i].id]) continue;
    if (i < N and p[i].x == p[i + 1].x and p[i].y == p[i + 1].y) {
      printf("%d %d\n", p[i].id, p[i + 1].id);
      vis[p[i].id] = vis[p[i + 1].id] = true;
    } else
      p2[++tot] = p[i];
  }
  sort(p2 + 1, p2 + 1 + tot);
  int tot3 = 0;
  for (int i = 1; i <= tot; ++i) {
    if (vis[p2[i].id]) continue;
    if (i < tot and p2[i].y == p2[i + 1].y) {
      printf("%d %d\n", p2[i].id, p2[i + 1].id);
      vis[p2[i].id] = vis[p2[i + 1].id] = true;
    } else
      p3[++tot3] = p2[i];
  }
  sort(p3 + 1, p3 + 1 + tot3);
  for (int i = 1, c = 1; i <= tot3; ++i, c = c ^ 1)
    printf("%d%c", p3[i].id, c ? ' ' : '\n');
  return 0;
}
