#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma comment(linker, "/STACK:2759005000")
using namespace std;
const long long MOD = 1e9 + 7;
const long long MOD1 = 7340033;
const long long BAS = 2500;
const long long dy[] = {1, -1, 0, 0};
const long long dx[] = {0, 0, 1, -1};
const long long N = 100000 / 400 + 5;
const long long INF = 1e18;
const double EPS = 1e-5;
const long double PI = 3.14159265358979323846;
const int SZ = 400;
const long long MAXN = 5e5 + 10;
int gcd(int a, int b) {
  if (a == 0) return b;
  return gcd(b % a, a);
}
map<int, vector<pair<pair<long long, long long>, long long>>> pl;
int n;
bool cmp(pair<pair<long long, long long>, long long> a,
         pair<pair<long long, long long>, long long> b) {
  if (a.first.first != b.first.first)
    return a < b;
  else
    return a.first.second < b.first.second;
}
pair<pair<long long, long long>, long long> mas[MAXN];
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cout.precision(2);
  srand(89398);
  cin >> n;
  for (int i = 0; i < n; i++) {
    int x, y, z;
    cin >> x >> y >> z;
    mas[i] = {{x, y}, y};
    pl[x].push_back({{y, z}, i});
  }
  pair<pair<long long, long long>, long long> last;
  bool has = 0;
  vector<pair<long long, long long>> ans;
  for (auto p : pl) {
    map<int, vector<pair<long long, long long>>> v;
    for (int i = 0; i < p.second.size(); i++) {
      v[p.second[i].first.first].push_back(
          {p.second[i].first.second, p.second[i].second});
    }
    bool hh = 0;
    pair<long long, long long> lastt;
    for (auto q : v) {
      sort((q.second).begin(), (q.second).end());
      for (int i = 0; i < q.second.size() - 1; i += 2) {
        cout << q.second[i].second + 1 << " " << q.second[i + 1].second + 1
             << "\n";
      }
      if (hh && q.second.size() % 2 == 1) {
        cout << lastt.second + 1 << " " << q.second.back().second + 1 << "\n";
        hh = 0;
        continue;
      }
      if (!hh && q.second.size() % 2 == 1) {
        hh = 1;
        lastt = q.second.back();
      }
    }
    if (hh && !has) {
      has = 1;
      int j = lastt.second;
      last = {{mas[j].first.second, mas[j].second}, j};
      continue;
    }
    if (hh && has) {
      has = 0;
      hh = 0;
      cout << lastt.second + 1 << " " << last.second + 1 << "\n";
    }
  }
  for (auto p : ans) cout << p.first << " " << p.second << "\n";
}
