#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using piii = pair<int, pii>;
using plll = pair<ll, pll>;
using pib = pair<int, bool>;
using pdi = pair<double, int>;
using pid = pair<int, double>;
using ld = long double;
using piiii = pair<pii, pii>;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
ll fpow(ll b, ll exp, ll mod) {
  if (exp == 0) return 1;
  ll t = fpow(b, exp / 2, mod);
  if (exp & 1) return t * t % mod * b % mod;
  return t * t % mod;
}
ll divmod(ll i, ll j, ll mod) {
  i %= mod, j %= mod;
  return i * fpow(j, mod - 2, mod) % mod;
}
struct point {
  int x, y, z, i;
};
int n, a, b, c;
vector<point> d3, d22, d32;
vector<vector<point>> d2, d1;
bool cmp1(point &p1, point &p2) { return p1.z < p2.z; }
bool cmp2(point &p1, point &p2) { return p1.x < p2.x; }
bool cmp3(point &p1, point &p2) { return p1.y < p2.y; }
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a >> b >> c;
    d3.push_back({a, b, c, i});
  }
  sort(d3.begin(), d3.end(), cmp1);
  queue<point> q;
  for (int i = 0; i < n; i++) {
    if (i > 0 && d3[i].z != d3[i - 1].z) {
      vector<point> cur;
      while (!q.empty()) {
        cur.push_back(q.front());
        q.pop();
      }
      d2.push_back(cur);
    }
    q.push(d3[i]);
  }
  vector<point> cur;
  while (!q.empty()) {
    cur.push_back(q.front());
    q.pop();
  }
  d2.push_back(cur);
  for (int i = 0; i < d2.size(); i++) {
    sort(d2[i].begin(), d2[i].end(), cmp2);
    d1.clear();
    for (int j = 0; j < d2[i].size(); j++) {
      if (j > 0 && d2[i][j].x != d2[i][j - 1].x) {
        vector<point> cur;
        while (!q.empty()) {
          cur.push_back(q.front());
          q.pop();
        }
        d1.push_back(cur);
      }
      q.push(d2[i][j]);
    }
    vector<point> cur;
    while (!q.empty()) {
      cur.push_back(q.front());
      q.pop();
    }
    d22.clear();
    d1.push_back(cur);
    for (int j = 0; j < d1.size(); j++) {
      sort(d1[j].begin(), d1[j].end(), cmp3);
      for (int k = 0; k < d1[j].size() - 1; k += 2) {
        cout << d1[j][k].i << " " << d1[j][k + 1].i << "\n";
      }
      if (d1[j].size() & 1) d22.push_back(d1[j].back());
    }
    sort(d22.begin(), d22.end(), cmp2);
    int x = d22.size() - 1;
    for (int j = 0; j < x; j += 2) {
      cout << d22[j].i << " " << d22[j + 1].i << "\n";
    }
    if (d22.size() & 1) d32.push_back(d22.back());
  }
  sort(d32.begin(), d32.end(), cmp1);
  for (int i = 0; i < d32.size(); i += 2) {
    cout << d32[i].i << " " << d32[i + 1].i << "\n";
  }
  return 0;
}
