#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll MOD = 1073741824;
using point = pair<pair<int, int>, int>;
map<int, vector<int>> zs;
point points[500005];
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    int x, y, z;
    cin >> x >> y >> z;
    zs[z].push_back(i);
    points[i] = {{x, y}, i};
  }
  set<int> s;
  for (auto& z : zs) {
    for (auto p : z.second) {
      s.insert(p);
    }
    vector<point> raw;
    for (int x : s) raw.push_back(points[x]);
    sort(begin(raw), end(raw));
    for (int i = 1; i < raw.size(); i++) {
      if (raw[i].first == raw[i - 1].first) {
        cout << raw[i].second << " " << raw[i - 1].second << endl;
        s.erase(raw[i].second);
        s.erase(raw[i - 1].second);
        break;
      }
    }
    map<int, vector<int>> ys;
    for (auto x : s) {
      ys[points[x].first.second].push_back(x);
    }
    set<int> s2;
    for (auto& y : ys) {
      for (int x : y.second) {
        s2.insert(x);
      }
      vector<point> raw2;
      for (int x : s2) raw2.push_back(points[x]);
      sort(begin(raw2), end(raw2));
      for (int i = 1; i < raw2.size(); i++) {
        if (raw2[i].first.first == raw2[i - 1].first.first) {
          cout << raw2[i].second << " " << raw2[i - 1].second << endl;
          s.erase(raw2[i].second);
          s.erase(raw2[i - 1].second);
          s2.erase(raw2[i].second);
          s2.erase(raw2[i - 1].second);
          break;
        }
      }
      vector<point> V2;
      for (int x : s2) V2.push_back(points[x]);
      sort(begin(V2), end(V2));
      for (int i = 1; i < V2.size(); i += 2) {
        cout << V2[i].second << " " << V2[i - 1].second << endl;
        s.erase(V2[i].second);
        s.erase(V2[i - 1].second);
        s2.erase(V2[i - 1].second);
        s2.erase(V2[i].second);
      }
    }
  }
}
