#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 5;
struct node {
  int x, y, z, id;
} a[N];
inline int cmp(node A, node B) {
  if (A.z != B.z) return A.z < B.z;
  if (A.x != B.x) return A.x < B.x;
  return A.y < B.y;
}
int vis[N];
inline void solve(int L, int R) {
  int odd = ((R - L + 1) & 1), num = (R - L + 1);
  for (int i = L; i <= R; ++i) {
    int l = i, r;
    while (i < R && a[i].x == a[i + 1].x) ++i;
    r = i;
    if (l != r) {
      for (int j = l; j <= r && j + 1 <= r; j += 2) {
        printf("%d %d\n", a[j].id, a[j + 1].id);
        vis[j] = 1, vis[j + 1] = 1, num -= 2;
      }
    }
  }
  int flag = 0;
  for (int i = L; i <= R; ++i) {
    if (vis[i]) continue;
    if (num == 1 && odd) break;
    (!flag) ? printf("%d ", a[i].id) : printf("%d\n", a[i].id);
    vis[i] = 1, flag ^= 1, --num;
  }
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i)
    scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z), a[i].id = i;
  sort(a + 1, a + n + 1, cmp);
  for (int i = 1; i <= n; ++i) {
    int l = i, r;
    while (i < n && a[i].z == a[i + 1].z) ++i;
    r = i;
    solve(l, r);
  }
  int flag = 0;
  for (int i = 1; i <= n; ++i) {
    if (vis[i]) continue;
    (!flag) ? printf("%d ", a[i].id) : printf("%d\n", a[i].id);
    flag ^= 1;
  }
}
