zoukankan      html  css  js  c++  java
  • LOJ#2586. 「APIO2018」选圆圈 KDtree+剪枝

    暴力枚举的话是 $O(n^2)$ 的,但是我们可以维护每个圆的外接矩阵,然后显然如果一个圆会被当前圆删,外接矩阵一定有交集,所以就可以用 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;  
    }
    

      

     

  • 相关阅读:
    not(expr|ele|fn)从匹配元素的集合中删除与指定表达式匹配的元素
    has(expr|ele)保留包含特定后代的元素,去掉那些不含有指定后代的元素。
    map(callback)将一组元素转换成其他数组(不论是否是元素数组)
    is(expr|obj|ele|fn)
    filter(expr|obj|ele|fn)筛选出与指定表达式匹配的元素集合。
    eq(index|-index)
    clone([Even[,deepEven]])克隆匹配的DOM元素并且选中这些克隆的副本。
    detach([expr]) 从DOM中删除所有匹配的元素。
    scrollTop([val])
    offset([coordinates])
  • 原文地址:https://www.cnblogs.com/guangheli/p/13034468.html
Copyright © 2011-2022 走看看