#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-6;
const int N = 200010;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
long long powmod(long long a, long long b) {
  long long res = 1;
  a %= mod;
  assert(b >= 0);
  for (; b; b >>= 1) {
    if (b & 1) res = res * a % mod;
    a = a * a % mod;
  }
  return res;
}
struct Node {
  int x, y, z, id;
} e[N], p[N], q[N], a[N], b[N];
int n, c2D, c3D;
void solve1D(int x) {
  sort(q + 1, q + 1 + x,
       [](const Node &a, const Node &b) { return a.x < b.x; });
  for (int i = 1; i < x; i += 2) {
    cout << q[i].id << " " << q[i + 1].id << endl;
  }
  if (x & 1) {
    a[++c2D] = q[x];
  }
}
void solve2D(int x) {
  sort(p + 1, p + 1 + x,
       [](const Node &a, const Node &b) { return a.y < b.y; });
  int now = 1, cnt = 0;
  c2D = 0;
  for (int i = 1; i <= x; i++) {
    now = i;
    while (now <= x && p[now].y == p[i].y) {
      q[++cnt] = p[now++];
    }
    i = now - 1;
    solve1D(cnt);
    cnt = 0;
  }
  for (int i = 1; i < c2D; i += 2) {
    cout << a[i].id << " " << a[i + 1].id << endl;
  }
  if (c2D & 1) {
    b[++c3D] = a[c2D];
  }
}
void solve3D() {
  sort(e + 1, e + 1 + n,
       [](const Node &a, const Node &b) { return a.z < b.z; });
  int now = 1, cnt = 0;
  for (int i = 1; i <= n; i++) {
    now = i;
    while (now <= n && e[now].z == e[i].z) {
      p[++cnt] = e[now++];
    }
    i = now - 1;
    solve2D(cnt);
    cnt = 0;
  }
  for (int i = 1; i < c3D; i += 2) {
    cout << b[i].id << " " << b[i + 1].id << endl;
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> e[i].x >> e[i].y >> e[i].z;
    e[i].id = i;
  }
  solve3D();
  return 0;
}
