#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'

using ii = pair<int, int>;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vec = vector<int>;

#define for0(i, n) for(int i = 0; i < n; ++i)
#define for1(i, n) for(int i = 1; i <= n; ++i)
#define fs first
#define sc second
#define sz(a) (int)a.size()
#define all(a) a.begin(), a.end()
#define pb push_back
#define CASE int _T; cin >> _T; for1(tt, _T)

namespace royyaha {
	// input
	template<typename T1, typename T2>													// vector
	void rvec(const T1 &n, vector<T2> &v) {
		v.resize(n); for0(i, n) cin >> v[i];
	}

	//output
	template<typename T> void pr(const T& x) { cout << x; }
	template<typename T1, typename T2>
	void pr(const pair<T1, T2>& x) {
		cout << x.first << " " << x.second;
    }
    template<typename T, typename... Args>
	void pr(const T& x, const Args&... rest) {
        pr(x); pr(rest...);
    }

	template<typename T> void ou(const T& x) { pr(x); cout << endl; }
	template<typename T, typename... Args>
	void ou(const T& x, const Args&... rest) { pr(x, ' '); ou(rest...); }
	template<typename T>
	void ou(const vector<T> &v) {
		for(auto it = v.begin(); it != v.end(); ++it) {									// vector
			if(it + 1 == v.end()) ou(*it);
			else pr(*it, ' ');
		}
	}

}
using namespace royyaha;

#ifdef rrr
#define wer(...) if(1) {																\
	cerr << __PRETTY_FUNCTION__ << " - " << __LINE__ << "(" << #__VA_ARGS__ << ") = ";	\
	ou(__VA_ARGS__);																	\
}
#define IOS
#else
#define wer(...)
#define IOS cin.tie(NULL); ios_base::sync_with_stdio(NULL);
#endif

struct point {
	int x, y, z;
	int id;
	bool operator < (const point &t) const {
		if(x != t.x) return x < t.x;
		else if(y != t.y) return y < t.y;
		return z < t.z;
	}
};

vector<point> v;
#define abs(x) (x > 0 ? x : -x)
ull r(point a, point b) {
	point c = {a.x - b.x, a.y - b.y, a.z - b.z};
	ull x = abs(c.x), y = abs(c.y), z = abs(c.z);
	return x * x + y * y + z * z;
}

bool used[50005] {};

signed main() {
	int n;
	cin >> n;
	v.resize(n);
	for0(i, n) {
		cin >> v[i].x >> v[i].y >> v[i].z;
		v[i].id = i + 1;
	}
	sort(all(v));
	reverse(all(v));
	for0(i, n) {
		cout << v[i].id << " " << v[i + 1].id << endl;
		i++;
	}
}


#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;

#define endl '\n'

using ii = pair<int, int>;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vec = vector<int>;

#define for0(i, n) for(int i = 0; i < n; ++i)
#define for1(i, n) for(int i = 1; i <= n; ++i)
#define fs first
#define sc second
#define sz(a) (int)a.size()
#define all(a) a.begin(), a.end()
#define pb push_back
#define CASE int _T; cin >> _T; for1(tt, _T)

namespace royyaha {
	// input
	template<typename T1, typename T2>													// vector
	void rvec(const T1 &n, vector<T2> &v) {
		v.resize(n); for0(i, n) cin >> v[i];
	}

	//output
	template<typename T> void pr(const T& x) { cout << x; }
	template<typename T1, typename T2>
	void pr(const pair<T1, T2>& x) {
		cout << x.first << " " << x.second;
    }
    template<typename T, typename... Args>
	void pr(const T& x, const Args&... rest) {
        pr(x); pr(rest...);
    }

	template<typename T> void ou(const T& x) { pr(x); cout << endl; }
	template<typename T, typename... Args>
	void ou(const T& x, const Args&... rest) { pr(x, ' '); ou(rest...); }
	template<typename T>
	void ou(const vector<T> &v) {
		for(auto it = v.begin(); it != v.end(); ++it) {									// vector
			if(it + 1 == v.end()) ou(*it);
			else pr(*it, ' ');
		}
	}

}
using namespace royyaha;

#ifdef rrr
#define wer(...) if(1) {																\
	cerr << __PRETTY_FUNCTION__ << " - " << __LINE__ << "(" << #__VA_ARGS__ << ") = ";	\
	ou(__VA_ARGS__);																	\
}
#define IOS
#else
#define wer(...)
#define IOS cin.tie(NULL); ios_base::sync_with_stdio(NULL);
#endif

signed main() {
	int n;
	cin >> n;
	vector<vec> p(n, vec(3));
	for0(i, n) {
		for0(j, 3) {
			cin >> p[i][j];
		}
	}

	auto solve = [&](auto& Self, vector<int> ids, int k) {
		if(k == 3) return ids[0];
		map<int, vec> mp;
		for(int i : ids) {
			mp[p[i][k]].pb(i);
		}
		vec ans;
		for(auto& t : mp) {
			int cur = Self(Self, t.sc, k + 1);
			if(cur != -1) ans.pb(cur);
		}
		for0(i, sz(ans) / 2) {
			cout << ans[i * 2] + 1 << " " << ans[i * 2 + 1] + 1 << endl;
		}
		if(sz(ans) % 2 == 1) return ans.back();
		else return -1;
	};

	vec t(n);
	iota(all(t), 0);
	solve(solve, t, 0);

}


#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'

using ii = pair<int, int>;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vec = vector<int>;

#define for0(i, n) for(int i = 0; i < n; ++i)
#define for1(i, n) for(int i = 1; i <= n; ++i)
#define fs first
#define sc second
#define sz(a) (int)a.size()
#define all(a) a.begin(), a.end()
#define pb push_back
#define CASE int _T; cin >> _T; for1(tt, _T)

namespace royyaha {
	// input
	template<typename T1, typename T2>													// vector
	void rvec(const T1 &n, vector<T2> &v) {
		v.resize(n); for0(i, n) cin >> v[i];
	}

	//output
	template<typename T> void pr(const T& x) { cout << x; }
	template<typename T1, typename T2>
	void pr(const pair<T1, T2>& x) {
		cout << x.first << " " << x.second;
    }
    template<typename T, typename... Args>
	void pr(const T& x, const Args&... rest) {
        pr(x); pr(rest...);
    }

	template<typename T> void ou(const T& x) { pr(x); cout << endl; }
	template<typename T, typename... Args>
	void ou(const T& x, const Args&... rest) { pr(x, ' '); ou(rest...); }
	template<typename T>
	void ou(const vector<T> &v) {
		for(auto it = v.begin(); it != v.end(); ++it) {									// vector
			if(it + 1 == v.end()) ou(*it);
			else pr(*it, ' ');
		}
	}

}
using namespace royyaha;

#ifdef rrr
#define wer(...) if(1) {																\
	cerr << __PRETTY_FUNCTION__ << " - " << __LINE__ << "(" << #__VA_ARGS__ << ") = ";	\
	ou(__VA_ARGS__);																	\
}
#define IOS
#else
#define wer(...)
#define IOS cin.tie(NULL); ios_base::sync_with_stdio(NULL);
#endif

vector<vec> p;

signed main() {
	int n;
	cin >> n;
	for0(i, n) {
		for0(j, 3) {
			cin >> p[i][j];
		}
	}

	auto solve = [&](auto& Self, vector<int> ids, int k) {
		if(k == 3) return ids[0];
		map<int, vec> mp;
		for(int i : ids) {
			mp[p[i][k]].pb(i);
		}
		vec ans;
		for(auto& t : mp) {
			int cur = Self(Self, t.sc, k + 1);
			if(cur != -1) ans.pb(cur);
		}
		for0(i, sz(ans) / 2) {
			cout << ans[i * 2] + 1 << " " << ans[i * 2 + 1] << endl;
		}
		if(sz(ans) % 2 == 1) return ans.back();
		else return -1;

	}

	vec t(n);
	iota(all(t), 0);
	solve(solve, t, 0);

}


#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'

using ii = pair<int, int>;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vec = vector<int>;

#define for0(i, n) for(int i = 0; i < n; ++i)
#define for1(i, n) for(int i = 1; i <= n; ++i)
#define fs first
#define sc second
#define sz(a) (int)a.size()
#define all(a) a.begin(), a.end()
#define pb push_back
#define CASE int _T; cin >> _T; for1(tt, _T)

namespace royyaha {
	// input
	template<typename T1, typename T2>													// vector
	void rvec(const T1 &n, vector<T2> &v) {
		v.resize(n); for0(i, n) cin >> v[i];
	}

	//output
	template<typename T> void pr(const T& x) { cout << x; }
	template<typename T1, typename T2>
	void pr(const pair<T1, T2>& x) {
		cout << x.first << " " << x.second;
    }
    template<typename T, typename... Args>
	void pr(const T& x, const Args&... rest) {
        pr(x); pr(rest...);
    }

	template<typename T> void ou(const T& x) { pr(x); cout << endl; }
	template<typename T, typename... Args>
	void ou(const T& x, const Args&... rest) { pr(x, ' '); ou(rest...); }
	template<typename T>
	void ou(const vector<T> &v) {
		for(auto it = v.begin(); it != v.end(); ++it) {									// vector
			if(it + 1 == v.end()) ou(*it);
			else pr(*it, ' ');
		}
	}

}
using namespace royyaha;

#ifdef rrr
#define wer(...) if(1) {																\
	cerr << __PRETTY_FUNCTION__ << " - " << __LINE__ << "(" << #__VA_ARGS__ << ") = ";	\
	ou(__VA_ARGS__);																	\
}
#define IOS
#else
#define wer(...)
#define IOS cin.tie(NULL); ios_base::sync_with_stdio(NULL);
#endif

struct point {
	int x, y, z;
	int id;
	bool operator < (const point &t) const {
		if(x != t.x) return x < t.x;
		else if(y != t.y) return y < t.y;
		return z < t.z;
	}
};

vector<point> v;
#define abs(x) (x > 0 ? x : -x)
ull r(point a, point b) {
	point c = {a.x - b.x, a.y - b.y, a.z - b.z};
	ull x = abs(c.x), y = abs(c.y), z = abs(c.z);
	return x * x + y * y + z * z;
}

bool used[50005] {};

signed main() {
	int n;
	cin >> n;
	v.resize(n);
	for0(i, n) {
		cin >> v[i].x >> v[i].y >> v[i].z;
		v[i].id = i + 1;
	}
	sort(all(v));
	reverse(all(v));
	int pre = 0;
	for1(i, n - 1) {
		if(v[pre].x == v[i].x && v[pre].y == v[i].y) {
			used[pre] = used[i] = true;
			cout << v[pre].id << " " << v[i].id << endl;
		} else {
			pre = i;
		}
	}
	pre = -1;
	for0(i, n) if(used[i] == false) {
		if(pre == -1) {
			pre = i;
		} else if(v[pre].x == v[i].x) {
			cout << v[pre].id << " " << v[i].id << endl;
			used[pre] = used[i] = true;
			pre = -1;
		}
	}
	pre = -1;
	for0(i, n) if(used[i] == false) {
		if(pre == -1) pre = i;
		else {
			cout << v[pre].id << " " << v[i].id << endl;
			pre = -1;
		}
	}
}


#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'

using ii = pair<int, int>;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vec = vector<int>;

#define for0(i, n) for(int i = 0; i < n; ++i)
#define for1(i, n) for(int i = 1; i <= n; ++i)
#define fs first
#define sc second
#define sz(a) (int)a.size()
#define all(a) a.begin(), a.end()
#define pb push_back
#define CASE int _T; cin >> _T; for1(tt, _T)

namespace royyaha {
	// input
	template<typename T1, typename T2>													// vector
	void rvec(const T1 &n, vector<T2> &v) {
		v.resize(n); for0(i, n) cin >> v[i];
	}

	//output
	template<typename T> void pr(const T& x) { cout << x; }
	template<typename T1, typename T2>
	void pr(const pair<T1, T2>& x) {
		cout << x.first << " " << x.second;
    }
    template<typename T, typename... Args>
	void pr(const T& x, const Args&... rest) {
        pr(x); pr(rest...);
    }

	template<typename T> void ou(const T& x) { pr(x); cout << endl; }
	template<typename T, typename... Args>
	void ou(const T& x, const Args&... rest) { pr(x, ' '); ou(rest...); }
	template<typename T>
	void ou(const vector<T> &v) {
		for(auto it = v.begin(); it != v.end(); ++it) {									// vector
			if(it + 1 == v.end()) ou(*it);
			else pr(*it, ' ');
		}
	}

}
using namespace royyaha;

#ifdef rrr
#define wer(...) if(1) {																\
	cerr << __PRETTY_FUNCTION__ << " - " << __LINE__ << "(" << #__VA_ARGS__ << ") = ";	\
	ou(__VA_ARGS__);																	\
}
#define IOS
#else
#define wer(...)
#define IOS cin.tie(NULL); ios_base::sync_with_stdio(NULL);
#endif

vector<vec> p;

signed main() {
	int n;
	cin >> n;
	for0(i, n) {
		for0(j, 3) {
			cin >> p[i][j];
		}
	}

	auto solve = [&](auto& Self, vector<int> ids, int k) {
		if(k == 3) return ids[0];
		map<int, vec> mp;
		for(int i : ids) {
			mp[p[i][k]].pb(i);
		}
		vec ans;
		for(auto& t : mp) {
			int cur = Self(Self, t.sc, k + 1);
			if(cur != -1) ans.pb(cur);
		}
		for0(i, sz(ans) / 2) {
			cout << ans[i * 2] + 1 << " " << ans[i * 2 + 1] << endl;
		}
		if(sz(ans) % 2 == 1) return ans.back();
		else return -1;

	};

	vec t(n);
	iota(all(t), 0);
	solve(solve, t, 0);

}


#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")

#define fi first
#define se second
#define LL long long

using namespace std;

const int N = 1e6 + 7;
const int mod = 1e9 + 7;
const int B = 317;

int n;
pair < pair < int , int > , pair < int , int > > p[N];

bool cmp(pair < pair < int , int > , pair < int , int > > x ,
         pair < pair < int , int > , pair < int , int > > y ){
    return x.fi.fi + x.se.fi + x.fi.se > y.fi.fi + y.fi.se + y.se.fi;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //freopen( "input.txt" , "r" , stdin );
    //freopen( "output.txt" , "w" , stdout );

    cin >> n;
    for( int i = 1; i <= n; i++ ){
        cin >> p[i].fi.fi >> p[i].fi.se >> p[i].se.fi;
        p[i].se.se = i;
    }
    sort( p + 1 , p + n + 1 , cmp );
    for( int i = n; i >= 1; i -= 2 ){
        cout << p[i].se.se << " " << p[i - 1].se.se << "\n";
    }
}


#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")

#define fi first
#define se second
#define LL long long

using namespace std;

const int N = 1e6 + 7;
const int mod = 1e9 + 7;
const int B = 317;

int n;
int a[N];
pair < pair < int , int > , pair < int , int > > p[N];
map < pair < int , int > , vector < int > > m;
map < int , vector < int > > g;

bool cmp( int x , int y ){
    return p[x].se.fi < p[y].se.fi;
}

bool cmp1( int x , int y ){
    return p[x].fi.se < p[y].fi.se;
}

bool cmp2( int x , int y ){
    return p[x].fi.fi < p[y].fi.fi;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //freopen( "input.txt" , "r" , stdin );
    //freopen( "output.txt" , "w" , stdout );

    cin >> n;
    for( int i = 1; i <= n; i++ ){
        cin >> p[i].fi.fi >> p[i].fi.se >> p[i].se.fi;
        p[i].se.se = i;
        int x = p[i].fi.fi;
        int y = p[i].fi.se;
        m[{x , y}].push_back(i);
    }
    for( auto x : m ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    for( int i = 1; i <= n; i++ ){
        if( !a[i] ){
            g[a[i]].push_back(i);
        }
    }
    for( auto x : g ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp1 );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    vector < int > v;
    for( int i = 1; i <= n; i++ ){
        if( !a[i] )v.push_back(i);
    }
    sort( v.begin() , v.end() , cmp2 );
    for( int i = 0; i < (int)v.size(); i += 2 ){
        cout << v[i] << " " << v[i + 1] << "\n";
    }
}


#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")

#define fi first
#define se second
#define LL long long

using namespace std;

const int N = 1e6 + 7;
const int mod = 1e9 + 7;
const int B = 317;

int n;
int a[N];
pair < pair < int , int > , pair < int , int > > p[N];
map < pair < int , int > , vector < int > > m;
map < int , vector < int > > g;

bool cmp( int x , int y ){
    return p[x].se.fi < p[y].se.fi;
}

bool cmp1( int x , int y ){
    return p[x].fi.se < p[y].fi.se;
}

bool cmp2( int x , int y ){
    return p[x].fi.fi < p[y].fi.fi;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //freopen( "input.txt" , "r" , stdin );
    //freopen( "output.txt" , "w" , stdout );

    cin >> n;
    for( int i = 1; i <= n; i++ ){
        cin >> p[i].fi.fi >> p[i].fi.se >> p[i].se.fi;
        p[i].se.se = i;
        int x = p[i].fi.fi;
        int y = p[i].fi.se;
        m[{x , y}].push_back(i);
    }
    for( auto x : m ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    for( int i = 1; i <= n; i++ ){
        if( !a[i] ){
            g[p[i].se.fi].push_back(i);
        }
    }
    for( auto x : g ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp1 );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    vector < int > v;
    for( int i = 1; i <= n; i++ ){
        if( !a[i] )v.push_back(i);
    }
    sort( v.begin() , v.end() , cmp2 );
    for( int i = 0; i < (int)v.size(); i += 2 ){
        cout << v[i] << " " << v[i + 1] << "\n";
    }
}


#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")

#define fi first
#define se second
#define LL long long

using namespace std;

const int N = 1e6 + 7;
const int mod = 1e9 + 7;
const int B = 317;

int n;
int a[N];
pair < pair < int , int > , pair < int , int > > p[N];
map < pair < int , int > , vector < int > > m;
map < int , vector < int > > g;

bool cmp( int x , int y ){
    return x > y;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //freopen( "input.txt" , "r" , stdin );
    //freopen( "output.txt" , "w" , stdout );

    cin >> n;
    for( int i = 1; i <= n; i++ ){
        cin >> p[i].fi.fi >> p[i].fi.se >> p[i].se.fi;
        p[i].se.se = i;
        int x = p[i].fi.fi;
        int y = p[i].fi.se;
        m[{x , y}].push_back(i);
    }
    for( auto x : m ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    for( int i = 1; i <= n; i++ ){
        if( !a[i] ){
            g[a[i]].push_back(i);
        }
    }
    for( auto x : g ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    vector < int > v;
    for( int i = 1; i <= n; i++ ){
        if( !a[i] )v.push_back(i);
    }
    sort( v.begin() , v.end() );
    for( int i = 0; i < (int)v.size(); i += 2 ){
        cout << v[i] << " " << v[i + 1] << "\n";
    }
}


#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")

#define fi first
#define se second
#define LL long long

using namespace std;

const int N = 1e6 + 7;
const int mod = 1e9 + 7;
const int B = 317;

int n;
int a[N];
pair < pair < int , int > , pair < int , int > > p[N];
map < pair < int , int > , vector < int > > m;
map < int , vector < int > > g;

bool cmp( int x , int y ){
    return p[x].se.fi < p[y].se.fi;
}

bool cmp1( int x , int y ){
    return p[x].fi.se < p[y].fi.se;
}

bool cmp2( int x , int y ){
    return p[x].fi.fi < p[y].fi.fi;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //freopen( "input.txt" , "r" , stdin );
    //freopen( "output.txt" , "w" , stdout );

    cin >> n;
    for( int i = 1; i <= n; i++ ){
        cin >> p[i].fi.fi >> p[i].fi.se >> p[i].se.fi;
        p[i].se.se = i;
        int x = p[i].fi.fi;
        int y = p[i].fi.se;
        m[{x , y}].push_back(i);
    }
    for( auto x : m ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    for( int i = 1; i <= n; i++ ){
        if( !a[i] ){
            g[p[i].fi.fi].push_back(i);
        }
    }
    for( auto x : g ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp1 );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    vector < int > v;
    for( int i = 1; i <= n; i++ ){
        if( !a[i] )v.push_back(i);
    }
    sort( v.begin() , v.end() , cmp2 );
    for( int i = 0; i < (int)v.size(); i += 2 ){
        cout << v[i] << " " << v[i + 1] << "\n";
    }
}


#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")

#define fi first
#define se second
#define LL long long

using namespace std;

const int N = 1e6 + 7;
const int mod = 1e9 + 7;
const int B = 317;

int n;
int a[N];
pair < pair < int , int > , pair < int , int > > p[N];
map < pair < int , int > , vector < int > > m;
map < int , vector < int > > g;

bool cmp( int x , int y ){
    return p[x].se.fi < p[y].se.fi;
}

bool cmp1( int x , int y ){
    return p[x].fi.se < p[y].fi.se;
}

bool cmp2( int x , int y ){
    return p[x].fi.fi < p[y].fi.fi;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    freopen( "input.txt" , "r" , stdin );
    freopen( "output.txt" , "w" , stdout );

    cin >> n;
    for( int i = 1; i <= n; i++ ){
        cin >> p[i].fi.fi >> p[i].fi.se >> p[i].se.fi;
        p[i].se.se = i;
        int x = p[i].fi.fi;
        int y = p[i].fi.se;
        m[{x , y}].push_back(i);
    }
    for( auto x : m ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    for( int i = 1; i <= n; i++ ){
        if( !a[i] ){
            g[p[i].se.fi].push_back(i);
        }
    }
    for( auto x : g ){
        if( x.se.size() > 1 ){
            sort( x.se.begin() , x.se.end() , cmp1 );
            for( int i = 0; i + 1 < (int)x.se.size(); i += 2 ){
                cout << x.se[i] << " " << x.se[i + 1] << "\n";
                a[x.se[i]] = a[x.se[i + 1]] = 1;
            }
        }
    }
    vector < int > v;
    for( int i = 1; i <= n; i++ ){
        if( !a[i] )v.push_back(i);
    }
    sort( v.begin() , v.end() , cmp2 );
    for( int i = 0; i < (int)v.size(); i += 2 ){
        cout << v[i] << " " << v[i + 1] << "\n";
    }
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 2005;

struct point{
    ll x, y, z;
    int vis;
    int id;

}num[maxn];

bool cmpx(const point& a, const point& b)
{
    if(a.vis == b.vis){
        if(a.x == b.x) {
            if(a.y == b.y) return a.z < b.z;
            return a.y < b.y;
        }
        return a.x < b.x;
    }
    return a.vis > b.vis;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        num[i].id = i;
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x && num[i].y == num[i+1].y) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+5;

struct point{
    ll x, y, z;
    int vis;
    int id;

}num[maxn];

bool cmpx(const point& a, const point& b)
{
    if(a.vis == b.vis){
        if(a.x == b.x) {
            if(a.y == b.y) return a.z < b.z;
            return a.y < b.y;
        }
        return a.x < b.x;
    }
    return a.vis > b.vis;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        num[i].id = i;
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x && num[i].y == num[i+1].y) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 2005;

struct point{
    double x, y, z;
    int id;
    double l;
    void lenth(const point& a)
    {
        double ans = (a.x - x) * (a.x - x) + (a.y - y) * (a.y - y) + (a.z - z) * (a.z - z);
        l = sqrt(ans);
    }
}num[maxn];

bool cmp(const point& a, const point& b)
{
    return a.l < b.l;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        m.x += num[i].x;
        m.y += num[i].y;
        m.z += num[i].z;
        num[i].id = i;
    }
    m.x /= n;
    m.y /= n;
    m.z /= n;

    for(int i = 1; i <= n; i++) {
        num[i].lenth(m);
    }
    sort(num+1, num+n+1, cmp);
    for(int i = n/2; i >= 1; i--) {
        cout << num[i].id << " " << num[n-i+1].id << endl;
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 5e5+5;

struct point{
    ll x, y, z;
    int vis;
    int id;

}num[maxn];

bool cmpx(const point& a, const point& b)
{
    if(a.vis == b.vis){
        if(a.x == b.x) {
            if(a.y == b.y) return a.z < b.z;
            return a.y < b.y;
        }
        return a.x < b.x;
    }
    return a.vis > b.vis;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        num[i].id = i;
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x && num[i].y == num[i+1].y) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i++) {
        if(!num[i].vis) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 2005;

struct point{
    ll x, y, z;
    int id;

}num[maxn];

bool vis[maxn];

bool cmpx(const point& a, const point& b)
{
    if(a.x == b.x) {
        if(a.y == b.y) return a.z < b.z;
        return a.y < b.y;
    }
    return a.x < b.x;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        num[i].id = i;
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i <= n; i+=2) {
        cout << num[i].id << " " << num[i+1].id << endl;
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 5e5+5;

struct point{
    ll x, y, z;
    int vis;
    int id;

}num[maxn];

bool cmpx(const point& a, const point& b)
{
    if(a.vis == b.vis){
        if(a.x == b.x) {
            if(a.y == b.y) return a.z < b.z;
            return a.y < b.y;
        }
        return a.x < b.x;
    }
    return a.vis > b.vis;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        num[i].id = i;
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i < n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x && num[i].y == num[i+1].y) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i < n; i++) {
        if(!num[i].vis && num[i].x == num[i+1].x) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }
    sort(num+1, num+n+1, cmpx);
    for(int i = 1; i < n; i++) {
        if(!num[i].vis) {
            cout << num[i].id << " " <<num[i+1].id << endl;
            num[i].vis = num[i+1].vis = 1;
        }
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 2005;

struct point{
    double x, y, z;
    int id;
    double l;
    void lenth(const point& a)
    {
        double ans = (a.x - x) * (a.x - x) + (a.y - y) * (a.y - y) + (a.z - z) * (a.z - z);
        l = sqrt(ans);
    }
}num[maxn];

bool cmp(const point& a, const point& b)
{
    return a.l < b.l;
}

int main()
{
    IOS();
    int n;
    cin >> n;
    point m;
    m.x = m.y = m.z = 0;
    for(int i = 1; i <= n; i++) {
        cin >> num[i].x >> num[i].y >> num[i].z;
        m.x += num[i].x;
        m.y += num[i].y;
        m.z += num[i].z;
        num[i].id = i;
    }
    m.x /= n;
    m.y /= n;
    m.z /= n;

    for(int i = 1; i <= n; i++) {
        num[i].lenth(m);
    }
    sort(num+1, num+n+1, cmp);
    for(int i = 1; i <= n; i+=2) {
        cout << num[i].id << " " << num[i+1].id << endl;
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
/**
********************************************************************
******************* Author:Bisnu sarkar ****************************
********************************************************************
**/
#define ull            unsigned long long
#define ll             long long
#define vi             vector<int>
#define pb             push_back
#define mp             make_pair
#define pii            pair<int,int>
#define vit            vector<int> :: iterator
#define sit            set<int> :: iterator
#define vrit           vector<int> :: reverse iterator
#define ff             first
#define ss             second
#define endl           '\n';
#define what_is(x)     cerr << #x << " is " << x << endl;
///*....Debugger....*/
#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it){   cout << endl ;}

template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args)
{
    cerr << *it << " = " << a << ' ' ;
    err(++it, args...);
}
int ini(){int x; scanf("%d",&x);return x;}
long long inl(){ long long x;scanf("%lld",&x); return x;}
double ind(){double x; scanf("%lf",&x);return x;}
#define Iin ini();
#define Lin inl();
#define Din ind();

int set_1(int n,int pos){return n = (n | (1<<pos));}
int reset_0(int n,int pos){return n= n & ~(1<<pos);}
bool check_bit(int n,int pos){return n = n & (1<<pos);}

int dx[8]= {1,0,-1,0,-1,-1,1,1};
int dy[8]= {0,1,0,-1,-1,1,-1,1};
const int N = (int) 2e3 + 5;
const int M = (int) 1e9 + 7;
const double pi=2* acos(0.0);
const double eps=1e-9;

struct point
{
    int x,y,z,id;
};
point p[N];

int n;

bool cmp(point a,point b){
    if(a.x == b.x){
        if(a.y==b.y){
            return a.z<b.z;
        }
        else{
            return a.y<b.y;
        }
    }
    else{
        return a.x<b.x;
    }
}
std::vector<point> remain;
void solve(std::vector<point> v){
    std::vector<point> extra;

    for(int i=0;i<v.size();){
        int j=i,k=i;

        while(j<=n and v[j].y==v[i].y)++j;

        while(k+1 < j){
            printf("%d %d\n", v[k].id,v[k+1].id);
            k+=2;
        }
        if(k<j)extra.push_back(v[k]);
        i=j;
    }
    for(int i=0;i+1 < extra.size();i+=2){
        printf("%d %d\n", extra[i].id,extra[i+1].id);
    }
    if(extra.size() % 2){
        remain.push_back(extra.back());
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t=1,te=0;
    while(t--){
        cin>>n;

        for(int i=1;i<=n;i++){
            int xx,yy,zz;
            cin>>xx>>yy>>zz;
            p[i].x=xx,p[i].y=yy,p[i].z=zz,p[i].id=i;

        }
        sort(p+1,p+n+1,cmp);

        for(int i=1;i<=n;){
            std::vector<point> v;
            int j=i;
            while(j<=n and p[j].x==p[i].x)v.push_back(p[j++]);

            solve(v),i=j;
        }

        for(int i=0;i<remain.size();i+=2){
            printf("%d %d\n", remain[i].id,remain[i+1].id);
        }

        //printf("Case %d: ",++te);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
/**
********************************************************************
******************* Author:Bisnu sarkar ****************************
********************************************************************
**/
#define ull            unsigned long long
#define ll             long long
#define vi             vector<int>
#define pb             push_back
#define mp             make_pair
#define pii            pair<int,int>
#define vit            vector<int> :: iterator
#define sit            set<int> :: iterator
#define vrit           vector<int> :: reverse iterator
#define ff             first
#define ss             second
#define endl           '\n';
#define what_is(x)     cerr << #x << " is " << x << endl;
///*....Debugger....*/
#define error(args...) {vector <string> _v = split(#args, ','); err(_v.begin(), args); cout << endl;}
vector <string> split(const string &s, char c) {
    vector <string> v;
    stringstream ss(s); string x;
    while (getline(ss, x, c)) v.emplace_back(x);
    return move(v);
}
void err(vector <string> :: iterator it) {}
template <typename T, typename... Args>
void err(vector <string> :: iterator it, T a, Args... args) {
    cout << it -> substr((*it)[0] == ' ', it -> length()) << " = " << a << ", ";
    err(++it, args...);
}

int ini(){int x; scanf("%d",&x);return x;}
long long inl(){ long long x;scanf("%lld",&x); return x;}
double ind(){double x; scanf("%lf",&x);return x;}
#define Iin ini();
#define Lin inl();
#define Din ind();

int set_1(int n,int pos){return n = (n | (1<<pos));}
int reset_0(int n,int pos){return n= n & ~(1<<pos);}
bool check_bit(int n,int pos){return n = n & (1<<pos);}

int dx[8]= {1,0,-1,0,-1,-1,1,1};
int dy[8]= {0,1,0,-1,-1,1,-1,1};
const int N = (int) 1e6 + 5;
const int M = (int) 1e9 + 7;
const double pi=2* acos(0.0);
const double eps=1e-9;

int a[N];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t=1,te=0;
    cin>>t;
    while(t--){

        //printf("Case %d: ",++te);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
/**
********************************************************************
******************* Author:Bisnu sarkar ****************************
********************************************************************
**/
#define ull            unsigned long long
#define ll             long long
#define vi             vector<int>
#define pb             push_back
#define mp             make_pair
#define pii            pair<int,int>
#define vit            vector<int> :: iterator
#define sit            set<int> :: iterator
#define vrit           vector<int> :: reverse iterator
#define ff             first
#define ss             second
#define endl           '\n';
#define what_is(x)     cerr << #x << " is " << x << endl;
///*....Debugger....*/
#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it){   cout << endl ;}

template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args)
{
    cerr << *it << " = " << a << ' ' ;
    err(++it, args...);
}
int ini(){int x; scanf("%d",&x);return x;}
long long inl(){ long long x;scanf("%lld",&x); return x;}
double ind(){double x; scanf("%lf",&x);return x;}
#define Iin ini();
#define Lin inl();
#define Din ind();

int set_1(int n,int pos){return n = (n | (1<<pos));}
int reset_0(int n,int pos){return n= n & ~(1<<pos);}
bool check_bit(int n,int pos){return n = n & (1<<pos);}

int dx[8]= {1,0,-1,0,-1,-1,1,1};
int dy[8]= {0,1,0,-1,-1,1,-1,1};
const int N = (int) 5e4 + 5;
const int M = (int) 1e9 + 7;
const double pi=2* acos(0.0);
const double eps=1e-9;

struct point
{
    int x,y,z,id;
};
point p[N];

int n;

bool cmp(point a,point b){
    if(a.x == b.x){
        if(a.y==b.y){
            return a.z<b.z;
        }
        else{
            return a.y<b.y;
        }
    }
    else{
        return a.x<b.x;
    }
}
std::vector<point> remain;
void solve(std::vector<point> v){
    std::vector<point> extra;

    for(int i=0;i<v.size();){
        int j=i,k=i;

        while(j<=n and v[j].y==v[i].y)++j;

        while(k+1 < j){
            printf("%d %d\n", v[k].id,v[k+1].id);
            k+=2;
        }
        if(k<j)extra.push_back(v[k]);
        i=j;
    }
    for(int i=0;i+1 < extra.size();i+=2){
        printf("%d %d\n", extra[i].id,extra[i+1].id);
    }
    if(extra.size() % 2){
        remain.push_back(extra.back());
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t=1,te=0;
    while(t--){
        cin>>n;

        for(int i=1;i<=n;i++){
            int xx,yy,zz;
            cin>>xx>>yy>>zz;
            p[i].x=xx,p[i].y=yy,p[i].z=zz,p[i].id=i;

        }
        sort(p+1,p+n+1,cmp);

        for(int i=1;i<=n;){
            std::vector<point> v;
            int j=i;
            while(j<=n and p[j].x==p[i].x)v.push_back(p[j++]);

            solve(v),i=j;
        }

        for(int i=0;i<remain.size();i+=2){
            printf("%d %d\n", remain[i].id,remain[i+1].id);
        }

        //printf("Case %d: ",++te);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
/**
********************************************************************
******************* Author:Bisnu sarkar ****************************
********************************************************************
**/
#define ull            unsigned long long
#define ll             long long
#define vi             vector<int>
#define pb             push_back
#define mp             make_pair
#define pii            pair<int,int>
#define vit            vector<int> :: iterator
#define sit            set<int> :: iterator
#define vrit           vector<int> :: reverse iterator
#define ff             first
#define ss             second
#define endl           '\n';
#define what_is(x)     cerr << #x << " is " << x << endl;
///*....Debugger....*/
#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it){   cout << endl ;}

template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args)
{
    cerr << *it << " = " << a << ' ' ;
    err(++it, args...);
}
int ini(){int x; scanf("%d",&x);return x;}
long long inl(){ long long x;scanf("%lld",&x); return x;}
double ind(){double x; scanf("%lf",&x);return x;}
#define Iin ini();
#define Lin inl();
#define Din ind();

int set_1(int n,int pos){return n = (n | (1<<pos));}
int reset_0(int n,int pos){return n= n & ~(1<<pos);}
bool check_bit(int n,int pos){return n = n & (1<<pos);}

int dx[8]= {1,0,-1,0,-1,-1,1,1};
int dy[8]= {0,1,0,-1,-1,1,-1,1};
const int N = (int) 5e4 + 5;
const int M = (int) 1e9 + 7;
const double pi=2* acos(0.0);
const double eps=1e-9;

pair<int,pair<int,pair<int,int>> > p[N];

bool vis[N];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t=1,te=0;
    while(t--){
        int n;
        cin>>n;

        for(int i=1;i<=n;i++){
            int xx,yy,zz;
            cin>>xx>>yy>>zz;
            p[i]={xx,{yy,{zz,i}}};
        }
        sort(p+1,p+n+1);

        for(int i=1;i<n;i+=2){
            cout<<p[i].ss.ss.ss<<" "<<p[i+1].ss.ss.ss<<endl;
        }

        //printf("Case %d: ",++te);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
/**
********************************************************************
******************* Author:Bisnu sarkar ****************************
********************************************************************
**/
#define ull            unsigned long long
#define ll             long long
#define vi             vector<int>
#define pb             push_back
#define mp             make_pair
#define pii            pair<int,int>
#define vit            vector<int> :: iterator
#define sit            set<int> :: iterator
#define vrit           vector<int> :: reverse iterator
#define ff             first
#define ss             second
#define endl           '\n';
#define what_is(x)     cerr << #x << " is " << x << endl;
///*....Debugger....*/
#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it){   cout << endl ;}

template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args)
{
    cerr << *it << " = " << a << ' ' ;
    err(++it, args...);
}
int ini(){int x; scanf("%d",&x);return x;}
long long inl(){ long long x;scanf("%lld",&x); return x;}
double ind(){double x; scanf("%lf",&x);return x;}
#define Iin ini();
#define Lin inl();
#define Din ind();

int set_1(int n,int pos){return n = (n | (1<<pos));}
int reset_0(int n,int pos){return n= n & ~(1<<pos);}
bool check_bit(int n,int pos){return n = n & (1<<pos);}

int dx[8]= {1,0,-1,0,-1,-1,1,1};
int dy[8]= {0,1,0,-1,-1,1,-1,1};
const int N = (int) 5e4 + 5;
const int M = (int) 1e9 + 7;
const double pi=2* acos(0.0);
const double eps=1e-9;

struct point
{
    int x,y,z,id;
};
point p[N];

int n;

bool cmp(point a,point b){
    if(a.x == b.x){
        if(a.y==b.y){
            return a.z<b.z;
        }
        else{
            return a.y<b.y;
        }
    }
    else{
        return a.x<b.x;
    }
}
std::vector<point> remain;
void solve(std::vector<point> v){
    std::vector<point> extra;

    for(int i=0;i<v.size();){
        int j=i,k=i;

        while(j<v.size() and v[j].y==v[i].y)++j;

        while(k+1 < j){
            printf("%d %d\n", v[k].id,v[k+1].id);
            k+=2;
        }
        if(k<j)extra.push_back(v[k]);
        i=j;
    }
    for(int i=0;i+1 < extra.size();i+=2){
        printf("%d %d\n", extra[i].id,extra[i+1].id);
    }
    if(extra.size() % 2){
        remain.push_back(extra.back());
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t=1,te=0;
    while(t--){
        cin>>n;

        for(int i=1;i<=n;i++){
            int xx,yy,zz;
            cin>>xx>>yy>>zz;
            p[i].x=xx,p[i].y=yy,p[i].z=zz,p[i].id=i;

        }
        sort(p+1,p+n+1,cmp);

        for(int i=1;i<=n;){
            std::vector<point> v;
            int j=i;
            while(j<=n and p[j].x==p[i].x)v.push_back(p[j++]);

            solve(v),i=j;
        }

        for(int i=0;i<remain.size();i+=2){
            printf("%d %d\n", remain[i].id,remain[i+1].id);
        }

        //printf("Case %d: ",++te);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());
 	bool vis[n];
 	memset(vis,false,sizeof vis);
	F(i,0,n-2){
		if(v[i].first.first==v[i+1].first.first){
			cout<<v[i].second<<" "<<v[i+1].second<<endl;
			vis[i]=vis[i+1]=true;
			i++;
		}
	}
	int f=0;
	F(i,0,n-1){
		if(vis[i]==false){
			if(f==0){
				cout<<v[i].second<<" ";
				f=1;
			}
			else{
				cout<<v[i].second<<endl;
				f=0;
			}

		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());
 	bool vis[n];
 	memset(vis,false,sizeof vis);
	for(int i=n-1;i>0;i--){
		if(v[i].first.first==v[i-1].first.first){
			cout<<v[i].second<<" "<<v[i-1].second<<endl;
			vis[i]=vis[i-1]=true;
			i--;
		}
	}
	int f=0;
	F(i,0,n-1){
		if(vis[i]==false){
			if(f==0){
				cout<<v[i].second<<" ";
				f=1;
			}
			else{
				cout<<v[i].second<<endl;
				f=0;
			}

		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long

typedef vector <ll> VV;
bool comp(VV a,VV b){
	if(a[0]==b[0]){
		if(a[1]==b[1]){
			return a[2]<b[2];
		}
		else
			return a[1]<b[1];
	}
	else
		return a[0]<b[0];
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <vector <ll> > v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.push_back({x,y,z,i});
	}
	sort(v.begin(),v.end(),comp);

	ll a,b,c,d,l;
	while(int(v.size())>0){
		l=v.size()-1;
		a=v[l][0],b=v[l][1],c=v[l][2],d=v[l][3];
		if(v.size()>1 && a==v[l-1][0] && b==v[l-1][1]){
			cout<<d<<" "<<v[l-1][3]<<endl;
			v.pop_back();
		}
		else
			u.push_back({a,b,c,d});
		v.pop_back();
	}
	while(int(u.size())>0){
		l=u.size()-1;
		a=u[l][0],b=u[l][1],c=u[l][2],d=u[l][3];
		if(u.size()>1 && a==u[l-1][0]){
			cout<<d<<" "<<u[l-1][3]<<endl;
			u.pop_back();
		}
		else
			v.push_back({a,b,c,d});
		u.pop_back();
	}
	F(i,0,v.size()-1)
	{
		cout<<v[i][3]<<" "<<v[i+1][3]<<endl;
		i++;
	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());

 	ll a,b,c,d,l;
 	while(int(v.size())>0){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>0 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(int(u.size())>0){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>0 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	while(v.size()>0){
 		l=v.size()-1;
 		printf("%lld %lld\n",v[l].second,v[l-1].second);
 		v.pop_back();
 		v.pop_back();
 	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());

 	ll a,b,c,d,l;
 	while(v.size()){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>0 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(u.size()){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>0 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	while(v.size()){
 		l=v.size()-1;
 		cout<<v[l].second<<" "<<v[l-1].second<<endl;
 		v.pop_back();
 		v.pop_back();
 	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second<b.first.second.second;
		}
		else{
			return a.first.second.first<b.first.second.first;
		}
	}
	else{
		return a.first.first<b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end(),comparator);

 	ll a,b,c,d,l;
 	while(int(v.size())>0){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>1 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(int(u.size())>0){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>1 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	F(i,0,v.size()-1){
 		cout<<v[i].second<<" "<<v[i+1].second<<endl;
 		i++;
 	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());
 	bool vis[n-1];
 	memset(vis,false,sizeof vis);
	F(i,0,n-2){
		if(v[i].first.first==v[i+1].first.first){
			cout<<v[i].second<<" "<<v[i+1].second;
			vis[i]=vis[i+1]=true;
			i++;
		}
	}
	int f=0;
	F(i,0,n-1){
		if(vis[i]=false){
			if(f==0){
				cout<<v[i].second<<" ";
				f=1;
			}
			else{
				cout<<v[i].second<<endl;
				f=0;
			}

		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());

 	ll a,b,c,d,l;
 	while(int(v.size())>0){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>0 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(int(u.size())>0){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>0 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	while(v.size()>0){
 		l=v.size()-1;
 		cout<<v[l].second<<" "<<v[l-1].second<<endl;
 		v.pop_back();
 		v.pop_back();
 	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());
 	bool vis[n-1];
 	memset(vis,false,sizeof vis);
	F(i,0,n-2){
		if(v[i].first.first==v[i+1].first.first){
			cout<<v[i].second<<" "<<v[i+1].second<<endl;
			vis[i]=vis[i+1]=true;
			i++;
		}
	}
	int f=0;
	F(i,0,n-1){
		if(vis[i]==false){
			if(f==0){
				cout<<v[i].second<<" ";
				f=1;
			}
			else{
				cout<<v[i].second<<endl;
				f=0;
			}

		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());
 	bool vis[n];
 	memset(vis,false,sizeof vis);
	F(i,0,n-2){
		if(v[i].first.first==v[i+1].first.first){
			if(v[i].first.second.first==v[i+1].first.second.first){
				cout<<v[i].second<<" "<<v[i+1].second<<endl;
				vis[i]=vis[i+1]=true;
				i++;
			}
		}
	}
	int f=0;
	F(i,0,n-1){
		if(vis[i]==false){
			if(f==0){
				cout<<v[i].second<<" ";
				f=1;
			}
			else{
				cout<<v[i].second<<endl;
				f=0;
			}

		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second<b.first.second.second;
		}
		else{
			return a.first.second.first<b.first.second.first;
		}
	}
	else{
		return a.first.first<b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end(),comparator);

 	ll a,b,c,d,l;
 	while(int(v.size())>0){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>0 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(int(u.size())>0){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>0 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	while(v.size()>0){
 		l=v.size()-1;
 		printf("%lld %lld\n",v[l].second,v[l-1].second);
 		v.pop_back();
 		v.pop_back();
 	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second<b.first.second.second;
		}
		else{
			return a.first.second.first<b.first.second.first;
		}
	}
	else{
		return a.first.first<b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end(),comparator);

 	ll a,b,c,d,l;
 	while(int(v.size())>0){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>0 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(int(u.size())>0){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>0 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	F(i,0,v.size()-1){
 		cout<<v[i].second<<" "<<v[i+1].second<<endl;
 		i++;
 	}
}


    #include <bits/stdc++.h>
    using namespace std;
    #define F(i,a,b) for(int i=int(a);i<=int(b);i++)
    #define ll long long
    #define pb push_back
    typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
    bool comparator(PP a, PP b){
    	if(a.first.first==b.first.first)
    	{
    		if(a.first.second.first==b.first.second.first){
    			return a.first.second.second-b.first.second.second;
    		}
    		else{
    			return a.first.second.first-b.first.second.first;
    		}
    	}
    	else{
    		return a.first.first-b.first.first;
    	}
    }
    int main(){
    	ll n,x,y,z;
    	cin>>n;

    	vector <PP> v;
    	F(i,1,n){
    		cin>>x>>y>>z;
    		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
    	}

    	sort(v.begin(),v.end());

    	for(int i=n-1;i>0;i--){
    		cout<<v[i].second<<" "<<v[i-1].second<<endl;
    		i--;
    	}
    }


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back

typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}

int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v,u;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());

 	ll a,b,c,d,l;
 	while(int(v.size())){
 		l=v.size()-1;
 		a=v[l].first.first,b=v[l].first.second.first,c=v[l].first.second.second,d=v[l].second;
 		if(v.size()>0 && a==v[l-1].first.first && b==v[l-1].first.second.first){
 			cout<<d<<" "<<v[l-1].second<<endl;
 			v.pop_back();
 		}
 		else
 			u.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		v.pop_back();
 	}
 	while(int(u.size())){
 		l=u.size()-1;
 		a=u[l].first.first,b=u[l].first.second.first,c=u[l].first.second.second,d=u[l].second;
 		if(u.size()>0 && a==u[l-1].first.first){
 			cout<<d<<" "<<u[l-1].second<<endl;
 			u.pop_back();
 		}
 		else
 			v.push_back(make_pair(make_pair(a,make_pair(b,c)),d));
 		u.pop_back();
 	}
 	while(int(v.size())){
 		l=v.size()-1;
 		cout<<v[l].second<<" "<<v[l-1].second<<endl;
 		v.pop_back();
 		v.pop_back();
 	}
}


#include <bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=int(a);i<=int(b);i++)
#define ll long long
#define pb push_back
typedef pair < pair<ll,pair<ll,ll> >,ll> PP;
bool comparator(PP a, PP b){
	if(a.first.first==b.first.first)
	{
		if(a.first.second.first==b.first.second.first){
			return a.first.second.second-b.first.second.second;
		}
		else{
			return a.first.second.first-b.first.second.first;
		}
	}
	else{
		return a.first.first-b.first.first;
	}
}
int main(){
	ll n,x,y,z;
	cin>>n;

	vector <PP> v;
	F(i,1,n){
		cin>>x>>y>>z;
		v.pb(make_pair(make_pair(x,make_pair(y,z)),i));
	}

	sort(v.begin(),v.end());

	F(i,0,n-1){
		cout<<v[i].second<<" "<<v[i+1].second<<endl;
		i++;
	}
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y<b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
map<P,ms<node>>H;
map<int,ms<node>>T;
int vis[maxn];
ms<node>Q;
node get(ms<node>&Y)
{
    auto h=Y.begin();
    node hh=*h;
    Y.erase(h);
    return hh;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        H[{x,y}].insert({x,y,z,i});
    }
    for(auto &i:H)
    {
        while(i.second.size()>=2)
        {
            node q=get(i.second);
            node w=get(i.second);
            cout<<q.xu<<" "<<w.xu<<endl;
        }
        if(i.second.size())T[(*(i.second.begin())).x].insert(*(i.second.begin()));
    }
    for(auto &i:T)
    {
        while(i.second.size()>=2)
        {
            node q=get(i.second);
            node w=get(i.second);
            cout<<q.xu<<" "<<w.xu<<endl;
        }
        if(i.second.size())Q.insert(*(i.second.begin()));
    }
    while(Q.size()>=2)
    {
        node q=get(Q);
        node w=get(Q);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
ms<node>t;
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y>b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
void amend(node& q1,node& q2,node& q3)
{
    if(q3.x<=max(q2.x,q1.x) && q3.x>=min(q2.x,q1.x) && q3.y<=max(q2.y,q1.y) && q3.y>=min(q2.y,q1.y)    && q3.z<=max(q2.z,q1.z) && q3.z>=min(q2.z,q1.z)) {
        node zhong =q3;
        zhong =q1;
        q1=q3;
        q3=zhong;
    }
}
node get(ms<node> &t)
{
    node q=*t.begin();
    t.erase(t.begin());
    return q;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }
    while(t.size()>=2) {
        node q=get(t);
        auto qq=t.lower_bound(q);
        node w=*qq;
        t.erase(qq);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
ms<node>t;
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y<b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
void amend(node& q1,node& q2,node& q3)
{
    if(q3.x<=max(q2.x,q1.x) && q3.x>=min(q2.x,q1.x) && q3.y<=max(q2.y,q1.y) && q3.y>=min(q2.y,q1.y)    && q3.z<=max(q2.z,q1.z) && q3.z>=min(q2.z,q1.z)) {
        node zhong =q3;
        zhong =q1;
        q1=q3;
        q3=zhong;
    }
}
node get(ms<node> &t)
{
    node q=*t.begin();
    t.erase(t.begin());
    return q;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }
    while(t.size()>=2) {
        node q=get(t);
        auto qq=t.upper_bound(q);
        node w=*qq;
        t.erase(qq);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
ms<node>t;
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y>b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
void amend(node& q1,node& q2,node& q3)
{
    if(q3.x<=max(q2.x,q1.x) && q3.x>=min(q2.x,q1.x) && q3.y<=max(q2.y,q1.y) && q3.y>=min(q2.y,q1.y)    && q3.z<=max(q2.z,q1.z) && q3.z>=min(q2.z,q1.z)) {
        node zhong =q3;
        zhong =q1;
        q1=q3;
        q3=zhong;
    }
}
node get(ms<node> &t)
{
    node q=*t.begin();
    t.erase(t.begin());
    return q;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }

    while(t.size()>=2) {
        node q=get(t);
        auto qq=t.lower_bound(q);
        node w=*qq;
        t.erase(qq);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
ms<node>t;
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y<b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
void amend(node& q1,node& q2,node& q3)
{
    if(q3.x<=max(q2.x,q1.x) && q3.x>=min(q2.x,q1.x) && q3.y<=max(q2.y,q1.y) && q3.y>=min(q2.y,q1.y)    && q3.z<=max(q2.z,q1.z) && q3.z>=min(q2.z,q1.z)) {
        node zhong =q3;
        zhong =q1;
        q1=q3;
        q3=zhong;
    }
}
node get(ms<node> &t)
{
    node q=*t.begin();
    t.erase(t.begin());
    return q;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }
    while(t.size()>=4)
    {
        node q1=get(t), q2=get(t), q3=get(t), q4=get(t);
        amend(q1,q2,q3);
        amend(q1,q2,q4);
        t.insert(q3);
        t.insert(q4);
        cout<<q1.xu<<" "<<q2.xu<<endl;
    }
    if(t.size()==2)
    {
        node q=get(t),w=get(t);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
ms<node>t;
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y<b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
void amend(node& q1,node& q2,node& q3)
{
    if(q3.x<=max(q2.x,q1.x) && q3.x>=min(q2.x,q1.x) && q3.y<=max(q2.y,q1.y) && q3.y>=min(q2.y,q1.y)    && q3.z<=max(q2.z,q1.z) && q3.z>=min(q2.z,q1.z)) {
        node zhong =q3;
        zhong =q1;
        q1=q3;
        q3=zhong;
    }
}
node get(ms<node> &t)
{
    node q=*t.begin();
    t.erase(t.begin());
    return q;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }
    while(t.size()>=8)
    {
        node q1=get(t), q2=get(t), q3=get(t), q4=get(t);
        node q5=get(t), q6=get(t), q7=get(t), q8=get(t);
        amend(q1,q2,q3);
        amend(q1,q2,q4);
        amend(q1,q2,q5);
        amend(q1,q2,q6);
        amend(q1,q2,q7);
        amend(q1,q2,q8);
        t.insert(q3);
        t.insert(q4);
        t.insert(q5);
        t.insert(q6);
        t.insert(q7);
        t.insert(q8);
        cout<<q1.xu<<" "<<q2.xu<<endl;
    }
    while(t.size()>=4)
    {
        node q1=get(t), q2=get(t), q3=get(t), q4=get(t);
        amend(q1,q2,q3);
        amend(q1,q2,q4);
        t.insert(q3);
        t.insert(q4);
        cout<<q1.xu<<" "<<q2.xu<<endl;
    }
    if(t.size()==2)
    {
        node q=get(t),w=get(t);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
multiset<node>t;
bool operator<(const node& a,const node&b) {
    if (a.x != b.x)return a.x < b.x;
    else if (a.y != b.y)return a.y < b.y;
    else if (a.z != b.z)return a.z < b.z;
    else return a.xu < b.xu;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }
    int num=n/2;
    while(!t.empty())
    {
        auto q=(*(t.begin()));
        t.erase(t.begin());
        auto h=(*prev(t.end()));
        t.erase(prev(t.end()));
        a[num]=q.xu,b[num]=h.xu;
        num--;
    }
    fu(i,1,n/2)
    {
        cout<<a[i]<<" "<<b[i]<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define lson rt<<1,l,M
#define rson rt<<1|1,M+1,r
#define PI acos(-1)
#define MM int M=(l+r)>>1;
#define fu(i,r,t) for(int i=r;i<=t;i++)
#define fd(i,r,t) for(int i=r;i>=t;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int long long
#define endl '\n'
#define lcm(a,b) (a*b)/__gcd(a,b)
#define Case(i,ans) cout<<"Case "<<i<<": "<<ans<<endl;
#define cp(i,ans) printf("%.if",ans);
#define cpp(i,ans) cout<<setprecision(i)<<fixed<<ans<<endl;
#define ppb pop_back
#define ppf pop_front
#define pb push_back
#define pf push_front
#define pq priority_queue
#define lowbit(x) (x)&(-x)
#define all(V) V.begin(),V.end()
#define ms multiset
#define mod(x) ((x+mo_num)%mo_num)
#define vc vector
#define vct vector<int>
#define fa(i,V) for(auto i:V)
#define out(i) cout<<(i)<<endl;
#define fi first
#define se second
#define fun(i) fu(i,1,n)
#define fut(i) fu(i,1,t)
#define fum(i) fu(i,1,m)
#define ld long double
#define umap unordered_map
#define P pair<int,int>
#define SET set<int>
using namespace std;
const int INF=LLONG_MAX-1e10;
const int maxn=1e6+5;
const int mo_num=1e9+7;
int n,m,a[maxn],b[maxn],ans;
struct node{
    int x,y,z,xu;
};
ms<node>t;
bool operator<(const node&a,const node&b)
{
    if(a.x!=b.x)return a.x<b.x;
    else if(a.y!=b.y)return a.y<b.y;
    else if(a.z!=b.z)return a.z<b.z;
    else return a.xu<b.xu;
}
void amend(node& q1,node& q2,node& q3)
{
    if(q3.x<=max(q2.x,q1.x) && q3.x>=min(q2.x,q1.x) && q3.y<=max(q2.y,q1.y) && q3.y>=min(q2.y,q1.y)    && q3.z<=max(q2.z,q1.z) && q3.z>=min(q2.z,q1.z)) {
        node zhong =q3;
        zhong =q1;
        q1=q3;
        q3=zhong;
    }
}
node get(ms<node> &t)
{
    node q=*t.begin();
    t.erase(t.begin());
    return q;
}
int32_t main()
{
    IOS
    cin>>n;
    fun(i)
    {
        int x,y,z;
        cin>>x>>y>>z;
        t.insert({x,y,z,i});
    }
    while(t.size()>=2) {
        node q=get(t);
        auto qq=t.lower_bound(q);
        node w=*qq;
        t.erase(qq);
        cout<<q.xu<<" "<<w.xu<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
vector<int> *graph;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;
bool vis[n];
for(int i=0;i<n;i++)
vis[i]=false;
map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
pair<pair<long long, long long>,pair<long long, int> > b=*pts.lower_bound(a);
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
pair<pair<long long, long long>,pair<long long, int> > c=*pts.lower_bound(b);
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;
vector<int> *graph;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;
bool vis[n];
for(int i=0;i<n;i++)
vis[i]=false;
map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
  pair<pair<long long, long long>,pair<long long, int> > temp_pt=pt;
  temp_pt.first.second=temp_pt.second.first=temp_pt.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(temp_pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
a.second.first=a.second.second=-1;
if(pts.lower_bound(a)==pts.end()){
    a=*pts.rbegin();
    a.second.first=a.second.second=-1;
}
pair<pair<long long, long long>,pair<long long, int> > b=*pts.lower_bound(a);
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
b.second.second=-1;
if(pts.lower_bound(b)==pts.end()){
    b=*pts.rbegin();
    b.second.second=-1;
}
pair<pair<long long, long long>,pair<long long, int> > c=*pts.lower_bound(b);
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;
vector<int> *graph;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;
bool vis[n];
for(int i=0;i<n;i++)
vis[i]=false;
map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
pair<pair<long long, long long>,pair<long long, int> > b=*pts.lower_bound(a);
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
pair<pair<long long, long long>,pair<long long, int> > c=*pts.lower_bound(b);
cout<<c.second.second+1<<"\n";
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;

map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
  pair<pair<long long, long long>,pair<long long, int> > temp_pt=pt;
  temp_pt.first.second=temp_pt.second.first=temp_pt.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(temp_pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
a.second.first=a.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > b;
set<pair<pair<long long, long long>,pair<long long, int> > >::iterator it=pts.lower_bound(a);
if(it==pts.end()){
    it--;
}
if((*it).first.first>a.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=-1;
 it=pts.lower_bound(tt);
 it--;
}
b=*it;
b.second.first=b.second.second=-1;
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
b.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > c;
it=pts.lower_bound(b);
if(it==pts.end()){
    it--;
}
if((*it).first.first>b.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=-1;
 it=pts.lower_bound(tt);
 it--;
}
if((*it).first.second>b.first.second){
pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.second.first=tt.second.second=-1;
 it=pts.lower_bound(tt);
 it--;
}
c=*it;
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;

map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
  pair<pair<long long, long long>,pair<long long, int> > temp_pt=pt;
  temp_pt.first.second=temp_pt.second.first=temp_pt.second.second=INT_MIN;
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(temp_pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
a.second.first=a.second.second=INT_MIN;
pair<pair<long long, long long>,pair<long long, int> > b;
set<pair<pair<long long, long long>,pair<long long, int> > >::iterator it=pts.lower_bound(a);
if(it==pts.end()){
    it--;
}
if((*it).first.first>a.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=INT_MIN
 it=pts.lower_bound(tt);
 it--;
}
b=*it;
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
b.second.second=INT_MIN;
pair<pair<long long, long long>,pair<long long, int> > c;
it=pts.lower_bound(b);
if(it==pts.end()){
    it--;
}
if((*it).first.first>b.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=INT_MIN;
 it=pts.lower_bound(tt);
 it--;
}
if((*it).first.second>b.first.second){
pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.second.first=tt.second.second=INT_MIN;
 it=pts.lower_bound(tt);
 it--;
}
c=*it;
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;

map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
  pair<pair<long long, long long>,pair<long long, int> > temp_pt=pt;
  temp_pt.first.second=temp_pt.second.first=temp_pt.second.second=INT_MIN;
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(temp_pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
a.second.first=a.second.second=INT_MIN;
pair<pair<long long, long long>,pair<long long, int> > b;
set<pair<pair<long long, long long>,pair<long long, int> > >::iterator it=pts.lower_bound(a);
if(it==pts.end()){
    it--;
}
if((*it).first.first>a.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=INT_MIN;
 it=pts.lower_bound(tt);
 it--;
}
b=*it;
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
b.second.second=INT_MIN;
pair<pair<long long, long long>,pair<long long, int> > c;
it=pts.lower_bound(b);
if(it==pts.end()){
    it--;
}
if((*it).first.first>b.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=INT_MIN;
 it=pts.lower_bound(tt);
 it--;
}
if((*it).first.second>b.first.second){
pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.second.first=tt.second.second=INT_MIN;
 it=pts.lower_bound(tt);
 it--;
}
c=*it;
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;

map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
  pair<pair<long long, long long>,pair<long long, int> > temp_pt=pt;
  temp_pt.first.second=temp_pt.second.first=temp_pt.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(temp_pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
a.second.first=a.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > b;
set<pair<pair<long long, long long>,pair<long long, int> > >::iterator it=pts.lower_bound(a);
if(it==pts.end()){
    it--;
}
if((*it).first.first>a.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=-1;
 it=pts.lower_bound(tt);
 it--;
}
b=*it;
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
b.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > c;
it=pts.lower_bound(b);
if(it==pts.end()){
    it--;
}
if((*it).first.first>b.first.first){
 pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.first.second=tt.second.first=tt.second.second=-1;
 it=pts.lower_bound(tt);
 it--;
}
if((*it).first.second>b.first.second){
pair<pair<long long, long long>,pair<long long, int> > tt=*it;
 tt.second.first=tt.second.second=-1;
 it=pts.lower_bound(tt);
 it--;
}
c=*it;
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;
vector<int> *graph;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;

map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){

 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
 cout<<pt.second.second+1<<" ";
  pair<pair<long long, long long>,pair<long long, int> > temp_pt=pt;
  temp_pt.first.second=temp_pt.second.first=temp_pt.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(temp_pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    single_freq[a.first.first]--;
    double_freq[{a.first.first,a.first.second}]--;
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
a.second.first=a.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > b;
if(pts.lower_bound(a)==pts.end()){
    b=*pts.rbegin();
    b.second.first=b.second.second=-1;
}
else
b=*pts.lower_bound(a);
if(double_freq[{b.first.first,b.first.second}]==1){
    cout<<b.second.second+1<<"\n";
    single_freq[b.first.first]--;
    double_freq[{b.first.first,b.first.second}]--;
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
b.second.second=-1;
pair<pair<long long, long long>,pair<long long, int> > c;
if(pts.lower_bound(b)==pts.end()){
    c=*pts.rbegin();
}
else
c=*pts.lower_bound(b);
cout<<c.second.second+1<<"\n";
single_freq[c.first.first]--;
double_freq[{c.first.first,c.first.second}]--;
pts.erase(c);

}

}


#include<bits/stdc++.h>
using namespace std;
vector<int> *graph;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;
bool vis[n];
for(int i=0;i<n;i++)
vis[i]=false;
map<long long, int> single_freq;
map< pair<long long, long long>, int> double_freq;
set<pair<pair<long long, long long>,pair<long long, int> > >pts;
for(int i=0;i<n;i++){

    pair<pair<long long, long long>,pair<long long, int> > pt;
    cin>>pt.first.first>>pt.first.second>>pt.second.first;
    pt.second.second=i;
    pts.insert(pt);
    long long x=pt.first.first, y=pt.first.second;
    single_freq[x]++;
    double_freq[{x,y}]++;

}
while(!pts.empty()){
cout<<(*pts.begin()).second.second+1<<" ";
 pair<pair<long long, long long>,pair<long long, int> > pt = *pts.begin();
 pts.erase(pts.begin());
pair<pair<long long, long long>,pair<long long, int> > a=*pts.lower_bound(pt);
if(single_freq[a.first.first]==1){
    cout<<a.second.second+1<<"\n";
    pts.erase(a);
    continue;
}

a.first.second=pt.first.second;
pair<pair<long long, long long>,pair<long long, int> > b=*pts.lower_bound(a);
if(double_freq[{b.first.second,b.second.first}]==1){
    cout<<b.second.second+1<<"\n";
    pts.erase(b);
    continue;
}
b.second.first=pt.second.first;
pair<pair<long long, long long>,pair<long long, int> > c=*pts.lower_bound(b);
cout<<c.second.second+1<<"\n";
pts.erase(c);

}

}


#include<stdio.h>
#include<string.h>

int main()
{
    int n, i, j, count = 0;
    scanf ("%d", &n);
    char str[n][102];
    for (i = 0; i < n; i++) {
        scanf ("%s", str[i]);
    }
    for (i = 0; i < n; i++) {
        count = 0;
        for (j = 0; j < n; j++) {
            if (str[i][j] != 'o') {
                if (str[i][j+1]=='o')
                    count++;
                if (str[i][j-1]=='o')
                    count++;
                if (str[i+1][j]=='o')
                    count++;
                if (str[i-1][j]=='o')
                    count++;
            }
        }
       if (count & 1) {
           printf ("NO\n");
           return 0;
       }
    }
    printf ("YES\n");
    return 0;
}