APIO 2018选圆圈

时间:2023-03-09 22:35:25
APIO 2018选圆圈
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#define sqr(x) (x) * (x)
#define M 300005
using namespace std;
const double inf = 1e20, eps = 1e-, alpha = acos(-) / , cosa = cos(alpha), sina = sin(alpha);
int n, root, ans[M], D,lc[M], rc[M], id[M];
double maxx[M][], minn[M][], deed[M][], rn[M];
int read() {
int nm = , f =;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -;
for(; isdigit(c); c = getchar()) nm = nm * + c - '';
return nm * f;
} struct C {
double d[], r;
int id;
bool operator < (C b) const {
return d[D] < b.d[D];
}
double& operator [](int x) {
return d[x];
} } note[M]; bool cmp(C a, C b) {
return a.r == b.r ? a.id < b.id : a.r > b.r;
} void updata(int x) {
for(int i = ; i <= ; i++) {
maxx[x][i] = minn[x][i] = deed[x][i];
maxx[x][i] = max(maxx[x][i], max(maxx[lc[x]][i], maxx[rc[x]][i]));
minn[x][i] = min(minn[x][i], min(minn[lc[x]][i], minn[rc[x]][i]));
}
} int build(int l, int r, int kx) {
if(l > r) return ;
int mid = (l + r) >> ;
D = kx;
nth_element(note + l, note + mid, note + r + );
deed[mid][] = note[mid][], deed[mid][] = note[mid][];
id[mid] = note[mid].id;
rn[mid] = note[mid].r;
lc[mid] = build(l, mid - , kx ^ ), rc[mid] = build(mid + , r, kx ^ );
updata(mid);
return mid;
}
bool check(int x, C a)
{
double xn = deed[x][], yn = deed[x][], xnn = a[], ynn = a[], r1 = rn[x], r2 = a.r; return sqr(xn - xnn) + sqr(yn - ynn) - sqr(r1 + r2)<= eps;
}
bool cut(int x, C a) {
double xn = a[], yn = a[], r = a.r + a.r; // 位被选中的圆形大小一定比当前小 依据这个来剪枝
if(xn + r + eps < minn[x][]) return true;
if(yn + r + eps < minn[x][]) return true;
if(xn - r - eps > maxx[x][]) return true;
if(yn - r - eps > maxx[x][]) return true;
return false;
}
void modify(int x, C a) {
if(x == ) return;
if(cut(x, a)) return;
if(!ans[id[x]] && check(x, a)) ans[id[x]] = a.id;
modify(lc[x], a) ,modify(rc[x], a);
} int main() {
maxx[][] = maxx[][] = -inf;
minn[][] = minn[][] = inf;
n = read();
for(int i = ; i <= n; i++) {
double x = read(), y = read(), z = read();
note[i] = (C) {
x * cosa - y * sina, x * sina + y * cosa, z, i
};
}
root = build(, n, );
sort(note + , note + n + , cmp);
for(int i = ; i <= n; i++)
if(!ans[note[i].id]) modify(root, note[i]);
for(int i = ; i <= n; i++) printf("%d ", ans[i]);
return ;
}