[APIO2018]选圆圈
题目
Solution:
kdtree裸题
Code:
#include<bits/stdc++.h>
#define ll long long
#define R register
#define lc t[p].ch[0]
#define rc t[p].ch[1]
template<class T>
void rea(T &x)
{
int f(0);char ch=getchar();x = 0;
while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
x = f?-x:x;
}
using namespace std;
int n, root, WD, ans[300005];
struct circle {int d[2], r, id;} cir[300005];
struct kdTREE
{
int ch[2], mx[2], mn[2];
circle c;
} t[1200005];
bool operator < (const circle &l, const circle &r) {return l.d[WD] < r.d[WD];}
inline bool cmp(const circle &l, const circle &r) { return (l.r == r.r) ? (l.id < r.id) : (l.r > r.r); }
int cnt;
void update(int p)
{
for(R int i = 0; i <= 1; ++i)
{
int r = t[p].c.r;
t[p].mx[i] = t[p].c.d[i]+r, t[p].mn[i] = t[p].c.d[i]-r;
if(lc) t[p].mx[i] = max(t[lc].mx[i], t[p].mx[i]), t[p].mn[i] = min(t[lc].mn[i], t[p].mn[i]);
if(rc) t[p].mx[i] = max(t[rc].mx[i], t[p].mx[i]), t[p].mn[i] = min(t[rc].mn[i], t[p].mn[i]);
}
}
int build(int l, int r, int wd)
{
if(l > r) return 0;
int mid = l+r >> 1, p = ++cnt;
WD = wd; nth_element(&cir[l], &cir[mid], &cir[r+1]), t[p].c = cir[mid];
lc = build(l, mid-1, wd^1), rc = build(mid+1, r, wd^1);
update(p);
return p;
}
bool outside(kdTREE edg, circle c)
{
int x0 = c.d[0], x1 = c.d[1], r = c.r;
if (x0 + r < edg.mn[0]) return 1;
if (x0 - r > edg.mx[0]) return 1;
if (x1 + r < edg.mn[1]) return 1;
if (x1 - r > edg.mx[1]) return 1;
return 0;
}
bool crash(circle l, circle r) {return 1ll*(l.d[0]-r.d[0])*(l.d[0]-r.d[0])+1ll*(l.d[1]-r.d[1])*(l.d[1]-r.d[1]) <= 1ll*(l.r+r.r)*(l.r+r.r);}
void query(int p, circle c)
{
if(outside(t[p], c)) return;
if(!ans[t[p].c.id] && crash(t[p].c, c)) ans[t[p].c.id] = c.id;
if(lc) query(lc, c);
if(rc) query(rc, c);
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
rea(n);
for(R int i = 1; i <= n; ++i) rea(cir[i].d[0]), rea(cir[i].d[1]), rea(cir[i].r), cir[i].id = i;
root = build(1, n, 0);
sort(cir+1, cir+1+n, cmp);
for(R int i = 1; i <= n; ++i) if(!ans[cir[i].id]) query(root, cir[i]);
for(R int i = 1; i <= n; ++i) printf("%d ", ans[i]);
return 0;
}