• BZOJ4025 二分图(线段树分治+可撤销带权并查集)


    根据数据是区间,也是时间,应该可以想到时间线段树分治

    问题就是如何查询二分图。

    一般判定二分图就是判断是否存在奇数环。

    那么奇数环就是当我们加入一条边,如果他们本身是联通的并且距离为偶数,这样就是奇数,并且一旦找到奇数环,下面的时间永远是奇数环

    因此我们可以用带权并查集来维护距离信息,这是经典套路,本体距离只有奇偶,因此直接异或判断。

    但是我们回溯的时候需要撤销并查集,因此不能路径压缩,只能采用按秩合并的思路,并且记录栈,按插入的顺序再撤销他

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e5+10;
    struct node{
        int l,r;
        vector<pll> num;
    }tr[N<<2];
    struct seg{
        int x,y,f,mx,d;
    };
    int n,m,T;
    int p[N],sz[N],d[N];
    stack<seg> s;
    int ans[N];
    int find(int x){
        if(p[x]!=x){
            return find(p[x]);
        }
        return x;
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,r};
        }
        else{
            tr[u]={l,r};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
        }
    }
    void modify(int u,int l,int r,pll x){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].num.push_back(x);
            return ;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,r,x);
        if(r>mid)
            modify(u<<1|1,l,r,x);
    }
    void init(){
        int i;
        for(i=1;i<=n;i++){
            p[i]=i,d[i]=0,sz[i]=1;
        }
    }
    int getdis(int x){
        if(x!=p[x]){
            return (d[x]^getdis(p[x]));
        }
        return d[x];
    }
    void solve(int u){
        int i;
        int flag=0;
        int cnt=0;
        for(i=0;i<(int)tr[u].num.size();i++){
            int x=tr[u].num[i].first,y=tr[u].num[i].second;
            int pa=find(x),pb=find(y);
            if(pa==pb){
                int a=getdis(x);
                int b=getdis(y);
                if(a==b){
                    flag=1;
                    break;
                }
            }
            else{
                if(sz[pa]>sz[pb]){
                    swap(x,y);
                    swap(pa,pb);
                }
                int tmp=p[pa];
                p[pa]=pb;
                d[pa]=d[x]^d[y]^1;
                s.push({pa,pb,tmp,sz[pb],0});
                sz[pb]+=sz[pa];
                cnt++;
            }
        }
        if(!flag){
            if(tr[u].l==tr[u].r){
                ans[tr[u].l]=1;
            }
            else{
                int mid=tr[u].l+tr[u].r>>1;
                solve(u<<1);
                solve(u<<1|1);
            }
        }
        while(cnt--){
            auto tmp=s.top();
            s.pop();
            p[tmp.x]=tmp.f;
            sz[tmp.y]=tmp.mx;
            d[tmp.x]=tmp.d;
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m>>T;
        int i;
        build(1,1,T);
        for(i=1;i<=m;i++){
            int a,b,c,d;
            cin>>a>>b>>c>>d;
            modify(1,c+1,d,{a,b});
        }
        init();
        solve(1);
        for(i=1;i<=T;i++){
            if(ans[i]){
                cout<<"Yes"<<endl;
            }
            else{
                cout<<"No"<<endl;
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    持续集成
    Centos7配置安装及优化
    vi/vim如何添加或删除多行注释.
    [Ansible实战]-批量配置初始化主机环境.
    VW模板机准备
    一次CPU过载报警处理
    [Ansible实战]-免交互批量管理Zabbix
    [Ansible实战]-ansible初始化mysql数据库
    [Ansible实战]-ansible部署Redis-5.x集群
    远程管理服务(SSH).
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14124628.html
Copyright © 2020-2023  润新知