#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
long long Min(long long x, long long y) { return x < y ? x : y; }
long long Max(long long x, long long y) { return x > y ? x : y; }
long long R() {
  long long ans = 0, f = 1;
  char c = getchar();
  for (; c < '0' || c > '9'; c = getchar())
    if (c == '-') f = -1;
  for (; c >= '0' && c <= '9'; c = getchar()) ans = ans * 10 + c - '0';
  return ans * f;
}
int n, cnt;
struct Node {
  int x, y, z, id;
  bool friend operator<(Node a, Node b) {
    return a.x != b.x ? a.x < b.x : a.y < b.y;
  }
};
map<int, int> ma;
vector<Node> v[N], v3;
void Sol2(vector<Node> v) {
  sort(v.begin(), v.end());
  vector<Node> v2;
  for (int i = 0; i < (int)v.size(); ++i) {
    if (i + 1 != v.size())
      if (v[i].x == v[i + 1].x) {
        printf("%d %d\n", v[i].id, v[i + 1].id);
        ++i;
        continue;
      }
    v2.push_back(v[i]);
  }
  for (int i = 0; i + 1 < (int)v2.size(); i += 2)
    printf("%d %d\n", v2[i].id, v2[i + 1].id);
  if (v2.size() % 2 == 1) v3.push_back(v2.back());
}
bool cmp2(Node a, Node b) { return a.z < b.z; }
int main() {
  n = R();
  for (int i = 1; i <= n; ++i) {
    Node x;
    x.x = R();
    x.y = R();
    x.z = R();
    x.id = i;
    if (!ma[x.z]) ma[x.z] = ++cnt;
    v[ma[x.z]].push_back(x);
  }
  for (int i = 1; i <= cnt; ++i) Sol2(v[i]);
  sort(v3.begin(), v3.end(), cmp2);
  for (int i = 0; i < (int)v3.size(); i += 2)
    printf("%d %d\n", v3[i].id, v3[i + 1].id);
  return 0;
}
