LOJ#2586. 「APIO2018」选圆圈 KDtree+剪枝
直接做的话洛谷上能过,LOJ 上要在开始的时候把所有点都旋转一个特定的角度来保证随机性.
code:
#include <bits/stdc++.h>
#define N 300007
#define ll long long
#define inf 1000000000
#define eps 5e-2
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int d,n,ans[N];
double sqr(double x) { return x*x; }
struct data
{
int ch[2],si,id;
double p[2],mi[2],ma[2],cmi[2],cma[2],r;
bool operator<(const data b) const
{
return p[d]==b.p[d]?p[d^1]<b.p[d^1]:p[d]<b.p[d];
}
int out(data b)
{
int flag=0;
for(int i=0;i<2;++i)
if(mi[i]>b.ma[i]||ma[i]<b.mi[i]) flag=1;
return flag;
}
int check(data b)
{
double dis1=sqr(p[0]-b.p[0])+sqr(p[1]-b.p[1]);
double dis2=sqr(r+b.r);
return dis2-dis1>=-eps;
}
}s[N];
void pushup(int x,int y)
{
for(int i=0;i<2;++i)
{
s[x].mi[i]=min(s[x].mi[i],s[y].mi[i]);
s[x].ma[i]=max(s[x].ma[i],s[y].ma[i]);
}
}
int build(int l,int r,int o)
{
int mid=(l+r)>>1;
d=o,nth_element(s+l,s+mid,s+1+r),s[mid].si=1;
if(mid>l)
{
s[mid].ch[0]=build(l,mid-1,o^1);
pushup(mid,s[mid].ch[0]),s[mid].si+=s[s[mid].ch[0]].si;
}
if(r>mid)
{
s[mid].ch[1]=build(mid+1,r,o^1);
pushup(mid,s[mid].ch[1]),s[mid].si+=s[s[mid].ch[1]].si;
}
return mid;
}
struct cir
{
double x,y,r;
int id;
cir(double x=0,double y=0,int id=0,double r=0):x(x),y(y),id(id),r(r){}
bool operator<(const cir b) const { return r==b.r?id<b.id:r>b.r; }
}c[N];
int query(int x,data b,int fa)
{
if(!s[x].si||s[x].out(b)) return 0;
int tp=0;
if(!ans[s[x].id]&&s[x].check(b))
{
ans[s[x].id]=fa,tp=1;
s[x].mi[0]=s[x].mi[1]=s[x].cmi[0]=s[x].cmi[1]=inf;
s[x].ma[0]=s[x].ma[1]=s[x].cma[0]=s[x].cma[1]=-inf;
}
for(int i=0;i<2;++i)
s[x].mi[i]=s[x].cmi[i],s[x].ma[i]=s[x].cma[i];
if(s[x].ch[0]) tp+=query(s[x].ch[0],b,fa),pushup(x,s[x].ch[0]);
if(s[x].ch[1]) tp+=query(s[x].ch[1],b,fa),pushup(x,s[x].ch[1]);
s[x].si-=tp;
return tp;
}
const double sina=sqrt(2)/2;
const double cosa=sqrt(2)/2;
int main()
{
// setIO("input");
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
double a,b,r,x,y;
scanf("%lf%lf%lf",&a,&b,&r);
x=a*cosa-b*sina;
y=a*sina+b*cosa;
s[i].cmi[0]=s[i].mi[0]=x-r;
s[i].cma[0]=s[i].ma[0]=x+r;
s[i].cmi[1]=s[i].mi[1]=y-r;
s[i].cma[1]=s[i].ma[1]=y+r;
s[i].p[0]=x,s[i].p[1]=y,s[i].id=i,s[i].r=r;
c[i]=cir(x,y,i,r);
}
sort(c+1,c+1+n);
data tmp;
int root=build(1,n,0);
for(int i=1;i<=n;++i)
{
if(!ans[c[i].id])
{
tmp.p[0]=c[i].x,tmp.p[1]=c[i].y,tmp.r=c[i].r;
tmp.mi[0]=c[i].x-c[i].r,tmp.ma[0]=c[i].x+c[i].r;
tmp.mi[1]=c[i].y-c[i].r,tmp.ma[1]=c[i].y+c[i].r;
query(root,tmp,c[i].id);
}
}
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
return 0;
}

浙公网安备 33010602011771号