#pragma GCC optimize("O3,Ofast,unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
const int MAXN = 303030;
struct chash {
size_t operator()(const std::pair<int, int>& p) const {
size_t h1 = std::hash<int>{}(p.first);
size_t h2 = std::hash<int>{}(p.second);
return h1 ^ (h2 + 0x9e3779b97f4a7c15ULL + (h1 << 6) + (h1 >> 2));
}
};
struct Circle {
int x, y, r, id;
bool doesIntersect(const Circle& rhs) const {
ll dx = x - rhs.x;
ll dy = y - rhs.y;
ll pr = r + rhs.r;
return dx * dx + dy * dy <= pr * pr;
}
};
int floor_div(int a, int b) {
int q = a / b;
if((a^b) < 0 && q*b!=a) q--;
return q;
}
int n, a[MAXN];
Circle cx[MAXN];
int main()
{
ios_base::sync_with_stdio(false); cin.tie(NULL);
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> cx[i].x >> cx[i].y >> cx[i].r; cx[i].id = i;
}
auto rescale = [&](int R) -> gp_hash_table<pair<int, int>, vector<Circle*>, chash> {
gp_hash_table<pair<int, int>, vector<Circle*>, chash> res;
for(int i = 1; i <= n; i++) {
if(a[i]) continue;
int r = floor_div(cx[i].x, R);
int c = floor_div(cx[i].y, R);
res[{r,c}].push_back(&cx[i]);
}
return res;
};
int R = 1<<30;
vector<int> v(n);
iota(v.begin(), v.end(), 1);
sort(v.begin(), v.end(), [](int i, int j) { return tuple(-cx[i].r, i) < tuple(-cx[j].r, j); });
auto table = rescale(R);
for(auto i : v) {
if(a[i]) continue;
a[i] = i;
int oldR = R;
while(R/2 >= cx[i].r) R /= 2;
if(oldR != R) table = rescale(R);
int r = floor_div(cx[i].x, R);
int c = floor_div(cx[i].y, R);
for(int dr = -2; dr <= 2; dr++) {
for(int dc = -2; dc <= 2; dc++) {
for(auto c : table[{r+dr,c+dc}]) {
if(!a[c->id] && cx[i].doesIntersect(*c)) a[c->id] = i;
}
}
}
}
for(int i = 1; i <= n; i++) cout << a[i] << " ";
}