zoukankan      html  css  js  c++  java
  • ZOJ 3521 Fairy Wars oj错误题目,计算几何,尺取法,排序二叉树,并查集 难度:2

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3521 

    ATTENTION:如果用long long 减小误差,这道题只能用%lld读入

    首先需要判断哪些点是相互挨着的,这样比直接维护哪些集合是冰冻住的简单

    按照x为主,y为辅排序,在数组上尺取,当head与tail的x坐标相差大于l/2则把head向后移动直到x坐标满足条件,

    那么对于head到tail,现在的问题就只剩下检测出哪些点之间y间距小于l/2,把它们都按照pair<y,id>加入set,那么离tail最近的两个点的y坐标就是离tail最近的,如果其中某个点满足间距小于l/2,那么就把tail和这个点放在一个并查集里,(其他的点如果满足条件,会和这两个点在一个并查集里)

    最后统计一下哪些并查集是被冰冻住的,以及这些并查集中有多少点即可

    #include <cstdio>
    #include <cstring>
    #include <set>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxn=5e4+3;
    int n;
    ll r,l;
    P pnt[maxn],o;
    int par[maxn];
    bool in[maxn];
    
    ll dis(P a,P b){return (a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second);}
    
    int fnd(int i){return(par[i]==i?i:(par[i]=fnd(par[i])));}
    bool same(int a,int b){return fnd(a)==fnd(b);}
    void unite(int a,int b){
            if(!same(a,b)){
                    par[par[b]]=par[a];
            }
    }
    
    
    void solve(){
            set<P> st;
            int head=0;
            for(int tail=0;tail<n;tail++){
                    while(2*abs(pnt[tail].first-pnt[head].first)>l){
                            st.erase(P(pnt[head].second,head));
                            head++;
                    }
                    set<P>::iterator it = st.insert(P(pnt[tail].second,tail)).first;
                    if(it!=st.begin()){
                            it--;
    //printf("s:%lld %lld
    ",it->first,pnt[tail].second);
                            if(2*abs(pnt[tail].second-it->first)<=l){
                                    unite(tail,it->second);
                            }
                            it++;
                    }
    
                    it++;
                    if(it!=st.end()){
                            if(2*abs(it->first-pnt[tail].second)<=l){
                                    unite(tail,it->second);
                            }
                    }
            }
    }
    
    void output(){
            int ans=0;
            for(int i=0;i<n;i++){
                    if(dis(pnt[i],o)<=r*r){
                            if(!in[fnd(i)]){
                                    in[par[i]]=true;
                            }
                    }
            }
            for(int i=0;i<n;i++){
                    if(in[fnd(i)]){
                            ans++;
                    }
            }
    
            printf("%d
    ",ans);
    }
    int main(){
            while(scanf("%d%lld%lld",&n,&r,&l)==3){
                    memset(in,0,sizeof(in));
                    for(int i=0;i<n;i++){
                            scanf("%lld%lld",&(pnt[i].first),&(pnt[i].second));
                            par[i]=i;
                    }
                    scanf("%lld%lld",&(o.first),&(o.second));
    
                    sort(pnt,pnt+n);
    
                    solve();
                    output();
            }
            return 0;
    }
    

      

  • 相关阅读:
    摆动排序 II
    二进制中1的个数
    n的幂
    丢掉的数字
    phpcms直接取子栏目的内容、调用点击量的方法
    phpcms导航栏当前栏目选中方法
    PHP中的全局变量global和$GLOBALS的区别
    phpcms添加子栏目后的读取
    phpcms取内容发布管理中的来源
    cms替换主页
  • 原文地址:https://www.cnblogs.com/xuesu/p/4296912.html
Copyright © 2011-2022 走看看