[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;
}

posted @ 2020-03-12 22:13  Chopsticks  阅读(153)  评论(0编辑  收藏  举报