传送门:luogu4631
KD-tree乱搞剪枝就过了?
把每个圆看成 ( x − r , y − r , x + r , y + r ) (x-r,y-r,x+r,y+r) (x−r,y−r,x+r,y+r)的矩阵,KD-tree维护所有未标号圆,暴力判相交即可。
最好一开始瞎旋一下坐标
p.s
eps设成1e-6会WA,改成1e-3才能A?
#include
#define fi first
#define sc second
#define pb push_back
//#define ccosi
using namespace std;
const int N=3e5+10;
typedef long long ll;
typedef double db;
const db inf=1e233,eps=1e-3;
int n,col[N],rt,D;
db ag,sum,avr,vl[2];
struct P{db d[2];int r,id;}p[N],cur;
struct node{
int ch[2];P pt;
db mn[2],mx[2];
}t[N];
inline bool cmp(P a,P b){return a.d[D]<b.d[D];}
inline bool cmpr(P a,P b){return (a.r==b.r)?a.id<b.id:a.r>b.r;}
#ifndef ccosi
char buf[(1<<15)];int p1=0,p2=0;
inline char gc()
{
if(p1==p2) p1=0,p2=fread(buf,1,(1<<15),stdin);
return (p1==p2)?EOF:buf[p1++];
}
#endif
#ifdef ccosi
#define gc getchar
#endif
char cp;
template<class T>inline void rd(T &x)
{
cp=gc();x=0;int f=0;
for(;!isdigit(cp);cp=gc()) if(cp=='-') f=1;
for(;isdigit(cp);cp=gc()) x=x*10+(cp^48);
if(f) x=-x;
}
inline void prit(int x)
{if(x>9) prit(x/10);putchar('0'+(x%10));}
inline db sqr(db x){return x*x;}
inline void pu(int x)
{
int i,l=t[x].ch[0],r=t[x].ch[1];
for(int i=0;i<2;++i){
if(col[t[x].pt.id]) t[x].mn[i]=inf,t[x].mx[i]=-inf;
else t[x].mn[i]=t[x].pt.d[i]-t[x].pt.r,t[x].mx[i]=t[x].pt.d[i]+t[x].pt.r;
if(l) t[x].mn[i]=min(t[x].mn[i],t[l].mn[i]),t[x].mx[i]=max(t[x].mx[i],t[l].mx[i]);
if(r) t[x].mn[i]=min(t[x].mn[i],t[r].mn[i]),t[x].mx[i]=max(t[x].mx[i],t[r].mx[i]);
}
}
int build(int l,int r)
{
if(l>r) return 0;
int i,j,mid=(l+r)>>1;
for(j=0;j<2;++j){
for(sum=0,i=l;i<=r;++i) sum+=p[i].d[j];
avr=sum/(r-l+1);sum=0;
for(i=l;i<=r;++i) sum+=sqr(p[i].d[j]-avr);
vl[j]=sum;
}
D=(vl[1]>vl[0])?1:0;nth_element(p+l,p+mid,p+r+1,cmp);
t[mid].pt=p[mid];
t[mid].ch[0]=build(l,mid-1);t[mid].ch[1]=build(mid+1,r);
pu(mid);return mid;
}
inline bool ot(int x)
{
return (t[x].mn[0]-eps>cur.d[0]+cur.r || t[x].mn[1]-eps>cur.d[1]+cur.r ||
t[x].mx[0]+eps<cur.d[0]-cur.r || t[x].mx[1]+eps<cur.d[1]-cur.r);
}
inline bool inn(P a)
{return (sqr(a.d[0]-cur.d[0])+sqr(a.d[1]-cur.d[1])<sqr(a.r+cur.r)+eps);}
void fd(int x)
{
if(ot(x)) return;
if((!col[t[x].pt.id]) && inn(t[x].pt)) col[t[x].pt.id]=cur.id;
if(t[x].ch[0]) fd(t[x].ch[0]);
if(t[x].ch[1]) fd(t[x].ch[1]);
pu(x);
}
int main(){
srand(19260817);ag=rand()/(db)RAND_MAX;
int i,j,x,y,z;db cs=cos(ag),sn=sin(ag);
rd(n);
for(i=1;i<=n;++i) {
rd(x);rd(y);rd(z);
p[i].d[0]=cs*x+sn*y;p[i].d[1]=cs*y-sn*x;
p[i].r=z;p[i].id=i;
}
rt=build(1,n);sort(p+1,p+n+1,cmpr);
for(i=1;i<=n;++i) if(!col[p[i].id]){
cur=p[i];col[cur.id]=cur.id;fd(rt);
}
for(i=1;i<=n;++i) {prit(col[i]);if(i<n) putchar(' ');}
return 0;
}