zoukankan      html  css  js  c++  java
  • 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
    ";
    #else
        const char LL[]="%lld
    ";
    #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;
    }
  • 相关阅读:
    阿里高级技术专家谈开源DDD框架:COLA4.0,分离架构和组件
    react的setState到底是同步还是异步?
    JMeter入门教程
    手把手教你接口自动化测试 – SoapUI & Groovy
    解读Web应用程序安全性问题的本质
    python实现的json数据以HTTP GET,POST,PUT,DELETE方式页面请求
    Linux常用命令
    PV原语操作详解
    软考计算机网络原理之IP计算问题汇总
    化繁为简了解进程与线程
  • 原文地址:https://www.cnblogs.com/Gloid/p/10162001.html
Copyright © 2011-2022 走看看