BZOJ5465 APIO2018选圆圈(KD-Tree+堆)

  考虑乱搞,用矩形框圆放KD-Tree上,如果当前删除的圆和矩形有交就递归下去删。为防止被卡,将坐标系旋转一定角度即可。注意eps稍微设大一点,最好开上long double。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define N 300010
#define double long double
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
const double PI=acos(-1.0);
const double eps=1E-6;
int n,c,cnt,root,ans[N];
struct circle
{
    double d[2];int r,i;
    bool operator <(const circle&a) const
    {
        return d[c]<a.d[c];
    }
    void rotate(double alpha)
    {
        double u=d[0]*cos(alpha)-d[1]*sin(alpha);
        double v=d[0]*sin(alpha)+d[1]*cos(alpha);
        d[0]=u,d[1]=v;
    }
}a[N];
struct KDTree{int ch[2];double a[2][2];circle p;
}tree[N];
double sqr(double x){return x*x;}
bool iscross(circle x,circle y){return sqr(x.d[0]-y.d[0])+sqr(x.d[1]-y.d[1])<sqr(x.r+y.r)+eps;}
double max(double x,double y,double z){return max(max(x,y),z);}
double iscross(circle p,double a[2][2]){return sqr(max(p.d[0]-a[0][1],a[0][0]-p.d[0],(double)0))+sqr(max(p.d[1]-a[1][1],a[1][0]-p.d[1],(double)0))<sqr(p.r)+eps;}
void build(int &k,int l,int r,int op)
{
    if (l>r) return;
    k=++cnt,c=op;int mid=l+r>>1;nth_element(a+l,a+mid,a+r+1);
    tree[k].p=a[mid];
    tree[k].a[0][0]=a[mid].d[0]-a[mid].r,tree[k].a[0][1]=a[mid].d[0]+a[mid].r,
    tree[k].a[1][0]=a[mid].d[1]-a[mid].r,tree[k].a[1][1]=a[mid].d[1]+a[mid].r;
    for (int i=l;i<=r;i++)
    tree[k].a[0][0]=min(tree[k].a[0][0],a[i].d[0]-a[i].r),tree[k].a[0][1]=max(tree[k].a[0][1],a[i].d[0]+a[i].r),
    tree[k].a[1][0]=min(tree[k].a[1][0],a[i].d[1]-a[i].r),tree[k].a[1][1]=max(tree[k].a[1][1],a[i].d[1]+a[i].r);
    build(tree[k].ch[0],l,mid-1,op^1);
    build(tree[k].ch[1],mid+1,r,op^1);
}
void find(int k,circle x)
{
    if (!ans[tree[k].p.i]&&iscross(tree[k].p,x)) ans[tree[k].p.i]=x.i;
    if (tree[k].ch[0]&&iscross(x,tree[tree[k].ch[0]].a)) find(tree[k].ch[0],x);
    if (tree[k].ch[1]&&iscross(x,tree[tree[k].ch[1]].a)) find(tree[k].ch[1],x);
}
struct cmp
{
    bool operator ()(const circle&a,const circle&b) const
    {
        return a.r<b.r||a.r==b.r&&a.i>b.i;
    }
};
priority_queue<circle,vector<circle>,cmp> q;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj5465.in","r",stdin);
    freopen("bzoj5465.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read();
    for (int i=1;i<=n;i++)
    {
        a[i].d[0]=read(),a[i].d[1]=read(),a[i].i=i,a[i].r=read();
        a[i].rotate(PI/6);
        q.push(a[i]);
    }
    build(root,1,n,0);
    while (1)
    {
        while (!q.empty()&&ans[q.top().i]) q.pop();
        if (q.empty()) break;
        circle x=q.top();q.pop();ans[x.i]=x.i;
        find(root,x);
    }
    for (int i=1;i<=n;i++) printf("%d ",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Gloid/p/10162001.html