几何+鸽笼原理+dsu复杂度分析——cf995C

这题的证明用了鸽笼原理,感觉真的很精妙

自己傻逼写错了个地方,调了老半天

/*
性质,三个向量里必定存在两个向量,相加后模长<=r
    证明:三个向量(以及三个对应的反方向向量)中,
        必定有两个向量的夹角在[0,60]之间 -> 必有两个向量夹角在[120,180]之间 
所以三个合并成两个,重复这个过程, 用两个set维护当前两个向量,碰到要合并时小的往大的合并 
*/

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define N 200005

const double pi = acos(-1.0);

struct point{
    ll x,y,id,flag;
    bool operator<(const point & a)const {
        return id<a.id;
    }
    
}p[N];
int n,ans[N];
point k1,k2;
set<point>s1,s2; 
point operator + (const point & b,const point &a){
    point res;
    res.x=b.x+a.x;res.y=b.y+a.y;
    return res;
}
int check(point k1,point k2,ll D=1000000ll){
    point k=k1+k2;
    ll dis2=k.x*k.x+k.y*k.y;
    if(dis2<=(ll)D*D && abs(k.x)<=D && abs(k.y)<=D)return 1;
    return 0;
}
point inv(point k){
    point res=k;
    res.x*=-1;res.y*=-1;res.flag*=-1;
    return res; 
} 

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
        p[i].flag=1,p[i].id=i;
    }
    if(n==1){
        cout<<1<<"\n";return 0;
    }
    
    s1.insert(p[1]);s2.insert(p[2]);
    k1=p[1];k2=p[2];
    for(int i=3;i<=n;i++){
        if(s1.size()<s2.size())swap(s1,s2),swap(k1,k2);
        int f=0;
        if(check(k1,p[i])){
            s1.insert(p[i]);
            k1=k1+p[i];f=1;
        } 
        else if(check(k1,inv(p[i]))){
            s1.insert(inv(p[i]));
            k1=k1+inv(p[i]);f=2;
        } 
        else if(check(k2,p[i])){
            s2.insert(p[i]);
            k2=k2+p[i];f=3;
        } 
        else if(check(k2,inv(p[i]))){
            s2.insert(inv(p[i]));
            k2=k2+inv(p[i]);f=4;
        } 
        else if(check(k1,k2)){
            for(auto p:s2){
                s1.insert(p);
                k1=k1+p;
            }
            s2.clear();
            s2.insert(p[i]);k2=p[i];f=5;
        } else if(check(k1,inv(k2))){
            for(auto p:s2){
                s1.insert(inv(p));
                k1=k1+inv(p);
            }
            s2.clear();
            s2.insert(p[i]);k2=p[i];f=6;
        }
        
    }
    
    
    if(check(k1,k2,1500000ll)){
        for(auto p:s2)
            s1.insert(p);
    }else if(check(k1,inv(k2),1500000ll)){
        for(auto p:s2)
            s1.insert(inv(p));
    }
    
    if(s1.size()!=n){puts("error");}
    for(auto p:s1)
        ans[p.id]=p.flag;
    
    for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
} 
 

 

posted on 2020-03-23 17:34  zsben  阅读(173)  评论(0编辑  收藏  举报

导航