• cf1278D——树的性质+并查集+线段树/DFS判环


    昨天晚上本来想认真打一场的,,结果陪女朋友去了。。

    回来之后看了看D,感觉有点思路,结果一直到现在才做出来

    首先对所有线段按左端点排序,然后用并查集判所有边是否联通,即遍历每条边i,和前一条不覆盖它的边合并,和后一条不被它覆盖的边合并

    再用线段树求边的总条数

    ps.其实可以直接用并查集合并的思路,每个点往前往后连边,建图然后DFS判环/联通就可以了

    #include<bits/stdc++.h>
    #include<set>
    using namespace std;
    #define N 1000005
    
    int n,dp[N];
    pair<int,int>p[N];
    set<int> s;
    set<int>::iterator it; 
    
    int F[N],pre[N],r[N];
    int find(int x){
        return F[x]==x?x:F[x]=find(F[x]);
    } 
    
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int lazy[N<<2];
    void pushdown(int rt){
        if(lazy[rt]){
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            lazy[rt]=0;
        }
    }
    void update(int L,int R,int v,int l,int r,int rt){
        if(L<=l && R>=r){
            lazy[rt]+=v;
            return;
        }
        int m=l+r>>1;
        if(L<=m)update(L,R,v,lson);
        if(R>m)update(L,R,v,rson);
    }
    int query(int pos,int l,int r,int rt){
        if(l==r)return lazy[rt];
        pushdown(rt);
        int m=l+r>>1;
        if(pos<=m)return query(pos,lson);
        else return query(pos,rson);
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d%d",&p[i].first,&p[i].second);
        sort(p+1,p+1+n);
        for(int i=1;i<=n;i++)r[p[i].second]=i; 
         
        s.clear();
        for(int i=1;i<=n;i++)F[i]=i;
        
        int tot=0;
        
        for(int i=1;i<=n;i++){
            it = s.lower_bound(p[i].second);
            if(i==1 || it==s.begin()){//没有前驱 
                dp[p[i].second]=-1;
                s.insert(p[i].second);
            }
            else {//有前驱 
                it--;
                dp[p[i].second]=*it;
                int tmp=dp[*it];
                if(p[i].first<=tmp){
                    puts("NO");
                    return 0;
                }
                s.insert(p[i].second);
                
                int fu=find(i),fv=find(r[*it]);
                if(fu!=fv && p[i].first<=*it)
                    F[fu]=fv;
            }
            if(i<n){//找后继 
                int L=i+1,R=n,mid,ans=0;
                while(L<=R){
                    mid=L+R>>1;
                    if(p[mid].second>p[i].second)
                        ans=mid,R=mid-1;
                    else L=mid+1;
                }
                if(ans){
                    int fu=find(i),fv=find(ans);
                    if(fu!=fv && p[i].second >= p[ans].first)
                        F[fu]=fv;
                }
            }
            tot+=query(p[i].first,1,1000000,1)-query(p[i].second,1,1000000,1);
            update(p[i].first,p[i].second,1,1,1000000,1);
        }
        
        if(tot!=n-1){puts("NO");return 0;}
        
        int cnt=0;
        for(int i=1;i<=n;i++)
            if(find(i)==i)cnt++;
        if(cnt==1)puts("YES");
        else puts("NO");
    }
  • 相关阅读:
    Linux操作篇之配置Samba
    Chrome扩展实现网页图片右键上传(以E站图片搜索为例)
    Linux开机自动挂载NFS配置的一个误区
    ffmpeg指令解读海康威视摄像头
    linux服务器性能调优之tcp/ip性能调优
    多线程程序设计中的8条简单原则
    初识文件系统
    socket中的listen到底干了哪些事情?
    ip面向无连接?TCP面向连接?HTTP连接方式?
    网络层和数据链层的区别
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12072687.html
Copyright © 2020-2023  润新知