#include <bits/stdc++.h>
using namespace std;
const long long int md = 1e9 + 7;
const int N = 1e5;
const int K = 100011;
struct point {
  long long int x, y, z, idx;
  point() { this->x = this->y = this->z = this->idx = 0; }
  point(long long int x, long long int y, long long int z) {
    this->x = x, this->y = y, this->z = z;
    this->idx = 0;
  }
};
int n;
vector<point> v, after;
map<int, vector<point> > frZ;
vector<point> have;
map<pair<int, int>, vector<point> > frYZ;
vector<pair<int, int> > ans;
bool cum1(point &p1, point &p2) { return p1.x < p2.x; }
bool cum2(point &p1, point &p2) { return p1.y < p2.y; }
bool cum3(point &p1, point &p2) { return p1.z < p2.z; }
int taken[100000];
int main() {
  cin >> n;
  v.resize(n);
  for (int i = 0; i < n; i++) {
    cin >> v[i].x >> v[i].y >> v[i].z, v[i].idx = i;
    frZ[v[i].z].push_back(v[i]);
    frYZ[make_pair(v[i].y, v[i].z)].push_back(v[i]);
  }
  for (auto it = frYZ.begin(); it != frYZ.end(); it++) {
    if (it->second.size() > 1) {
      sort(it->second.begin(), it->second.end(), cum1);
      for (int i = 0; i < it->second.size(); i++)
        if (!taken[it->second[i].idx]) have.push_back(it->second[i]);
      if (have.size() > 1) {
        for (int i = 0; i < have.size() - (1 + (have.size() & 1)); i += 2) {
          ans.push_back(make_pair(have[i].idx, have[i + 1].idx));
          taken[have[i].idx] = taken[have[i + 1].idx] = 1;
        }
      }
    }
    have.clear();
  }
  for (auto it = frZ.begin(); it != frZ.end(); it++) {
    if (it->second.size() > 1) {
      sort(it->second.begin(), it->second.end(), cum2);
      for (int i = 0; i < it->second.size(); i++)
        if (!taken[it->second[i].idx]) have.push_back(it->second[i]);
      if (have.size() > 1) {
        for (int i = 0; i < have.size() - (1 + (have.size() & 1)); i += 2) {
          ans.push_back(make_pair(have[i].idx, have[i + 1].idx));
          taken[have[i].idx] = taken[have[i + 1].idx] = 1;
        }
      }
    }
    have.clear();
  }
  for (int i = 0; i < n; i++)
    if (!taken[i]) after.push_back(v[i]);
  sort(after.begin(), after.end(), cum3);
  for (int i = 0; i < after.size(); i += 2)
    ans.push_back(make_pair(after[i].idx, after[i + 1].idx));
  for (int i = 0; i < ans.size(); i++)
    cout << ans[i].first + 1 << " " << ans[i].second + 1 << endl;
  return 0;
}
