zoukankan      html  css  js  c++  java
  • 几何+鸽笼原理+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<<"
    ";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]<<" ";
    } 
     
  • 相关阅读:
    c++回调java方法
    c++ 11学习笔记--智能指针
    c++ 11学习笔记--Lambda 表达式(对比测试Lambda ,bind,Function Object)
    explicit构造函数和private
    c++ 11学习笔记--右值引用和移动构造语义
    c++ 11学习笔记-- 常量表达式(constexpr)
    从京东app学到的(1)
    从文轩商城app学到的
    AntV G2 toolTip 自定义显示
    Ant Design of Vue table表格 点击一行选中效果
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12553598.html
Copyright © 2011-2022 走看看