#include <bits/stdc++.h>
using namespace std;
template <typename T>
void __read(T& a) {
  cin >> a;
}
template <typename T, typename... Args>
void __read(T& a, Args&... args) {
  cin >> a;
  __read(args...);
}
mt19937 rnd(static_cast<unsigned>(
    chrono::steady_clock::now().time_since_epoch().count()));
void Solve() {
  long long n;
  __read(n);
  vector<tuple<long long, long long, long long, long long>> a(n), b;
  for (signed i = 0; i < (n); i++) {
    cin >> get<0>(a[i]) >> get<1>(a[i]) >> get<2>(a[i]);
    get<3>(a[i]) = i + 1;
  }
  sort((a).begin(), (a).end());
  for (long long i = 0; i < a.size(); ++i) {
    if (i + 1 < a.size() && get<0>(a[i]) == get<0>(a[i + 1]) &&
        get<1>(a[i]) == get<1>(a[i + 1])) {
      cout << get<3>(a[i]) << ' ' << get<3>(a[i + 1]) << '\n';
      i++;
    } else
      b.push_back(a[i]);
  }
  a = move(b);
  for (long long i = 0; i < a.size(); ++i) {
    if (i + 1 < a.size() && get<0>(a[i]) == get<0>(a[i + 1])) {
      cout << get<3>(a[i]) << ' ' << get<3>(a[i + 1]) << '\n';
      i++;
    } else
      b.push_back(a[i]);
  }
  a = move(b);
  for (long long i = 0; i < a.size(); ++i) {
    cout << get<3>(a[i]) << ' ' << get<3>(a[i + 1]) << '\n';
    i++;
  }
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  Solve();
  return 0;
}
