• bzoj3674: 可持久化并查集


    用可持久化线段树维护可持久化并查集。

    调了一下午,改为按秩合并就过了。。。

    没路径压缩的:

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=200100;
    const int INF=1e9+10;
    
    int n,m;
    int fa[maxn];
    int u,v,op;
    int rk[maxn];
    
    int bug=0;
    
    struct SegTree
    {
        int l,r;
        int ls,rs;
        int sum;
        void debug()
        {
            printf("l=%2d r=%2d ls=%2d rs=%2d sum=%2d
    ",l,r,ls,rs,sum);
        }
    };SegTree T[maxn*64];
    int root[maxn],tot;
    
    void push_up(int rt)
    {
        T[rt].sum=T[T[rt].ls].sum+T[T[rt].rs].sum;
    }
    
    int build(int l,int r)
    {
        int k=++tot;
        T[k].l=l;T[k].r=r;
        T[k].ls=-1;T[k].rs=-1;
        T[k].sum=0;
        if(l==r){
            T[k].sum=fa[l];
            return k;
        }
        int m=(l+r)>>1;
        T[k].ls=build(l,m);
        T[k].rs=build(m+1,r);
        push_up(k);
        return k;
    }
    
    int update(int rt,int p,int c)
    {
        int k=++tot;
        T[k]=T[rt];
        if(T[rt].l==T[rt].r){
            T[k].sum=c;
            return k;
        }
        int m=(T[rt].l+T[rt].r)>>1;
        if(p<=m) T[k].ls=update(T[rt].ls,p,c);
        else T[k].rs=update(T[rt].rs,p,c);
        push_up(k);
        return k;
    }
    
    int query(int rt,int p)
    {
        if(T[rt].l==T[rt].r) return T[rt].sum;
        int m=(T[rt].l+T[rt].r)>>1;
        if(p<=m) return query(T[rt].ls,p);
        else return query(T[rt].rs,p);
    }
    
    int find(int k,int x)
    {
        int y=query(root[k],x);
        if(y==x) return x;
        else{
            int f=find(k,y);
            //update(root[k],x,f);  ///似乎不能路径压缩
            return f;
        }
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&n,&m)){
            REP(i,1,n) fa[i]=i,rk[i]=1;
            root[0]=build(1,n);
            int las=0;
            REP(i,1,m){
                scanf("%d",&op);
                if(op==1){
                    scanf("%d%d",&u,&v);
                    u^=las;v^=las;
                    int x=find(i-1,u),y=find(i-1,v);
                    if(rk[x]>rk[y]) swap(x,y);
                    if(x!=y) root[i]=update(root[i-1],x,y),rk[y]+=rk[x],rk[x]=0;
                    else root[i]=root[i-1];
                }
                else if(op==2){
                    scanf("%d",&u);
                    u^=las;
                    root[i]=root[u];
                }
                else{
                    scanf("%d%d",&u,&v);
                    u^=las;v^=las;
                    int x=find(i-1,u),y=find(i-1,v);
                    if(x==y) las=1;
                    else las=0;
                    root[i]=root[i-1];
                    printf("%d
    ",las);
                }
            }
        }
        return 0;
    }
    View Code

    路径压缩(不一定正确,但是莫名其妙地过了...)

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=200100;
    const int INF=1e9+10;
    
    int n,m;
    int fa[maxn];
    int u,v,op;
    int rk[maxn];
    
    int bug=0;
    
    struct SegTree
    {
        int l,r;
        int ls,rs;
        int sum;
        void debug()
        {
            printf("l=%2d r=%2d ls=%2d rs=%2d sum=%2d
    ",l,r,ls,rs,sum);
        }
    };SegTree T[maxn*64];
    int root[maxn],tot;
    
    void push_up(int rt)
    {
        T[rt].sum=T[T[rt].ls].sum+T[T[rt].rs].sum;
    }
    
    int build(int l,int r)
    {
        int k=++tot;
        T[k].l=l;T[k].r=r;
        T[k].ls=-1;T[k].rs=-1;
        T[k].sum=0;
        if(l==r){
            T[k].sum=fa[l];
            return k;
        }
        int m=(l+r)>>1;
        T[k].ls=build(l,m);
        T[k].rs=build(m+1,r);
        push_up(k);
        return k;
    }
    
    int update(int rt,int p,int c)
    {
        int k=++tot;
        T[k]=T[rt];
        if(T[rt].l==T[rt].r){
            T[k].sum=c;
            return k;
        }
        int m=(T[rt].l+T[rt].r)>>1;
        if(p<=m) T[k].ls=update(T[rt].ls,p,c);
        else T[k].rs=update(T[rt].rs,p,c);
        push_up(k);
        return k;
    }
    
    int query(int rt,int p)
    {
        if(T[rt].l==T[rt].r) return T[rt].sum;
        int m=(T[rt].l+T[rt].r)>>1;
        if(p<=m) return query(T[rt].ls,p);
        else return query(T[rt].rs,p);
    }
    
    int find(int k,int x)
    {
        int y=query(root[k],x);
        if(y==x) return x;
        else{
            int f=find(k,y);
            update(root[k],x,f);
            return f;
        }
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&n,&m)){
            REP(i,1,n) fa[i]=i,rk[i]=1;
            root[0]=build(1,n);
            int las=0;
            REP(i,1,m){
                scanf("%d",&op);
                if(op==1){
                    scanf("%d%d",&u,&v);
                    u^=las;v^=las;
                    int x=find(i-1,u),y=find(i-1,v);
                    if(rk[x]>rk[y]) swap(x,y);
                    if(x!=y) root[i]=update(root[i-1],x,y),rk[y]+=rk[x],rk[x]=0;
                    else root[i]=root[i-1];
                }
                else if(op==2){
                    scanf("%d",&u);
                    u^=las;
                    root[i]=root[u];
                }
                else{
                    scanf("%d%d",&u,&v);
                    u^=las;v^=las;
                    int x=find(i-1,u),y=find(i-1,v);
                    if(x==y) las=1;
                    else las=0;
                    root[i]=root[i-1];
                    printf("%d
    ",las);
                }
            }
        }
        return 0;
    }
    View Code

    update------

    似乎发现了一个问题,这个可持久化并查集不路径压缩但是按秩合并的话每次查询复杂度logn(树的深度),而路径压缩的正确性还有待验证。。如果能路径压缩的话复杂度就是常数级别(接近o(1))。

    update-----

    又发现了一个问题。。按秩合并有两种,一种是按集合大小合并,另一种是按树的深度合并。

    按深度合并只要设深度为h[maxn],将深度小的合并到深度大的,

    然后合并时加一句 if(h[x]>h[y]) swap(x,y);  ...   h[y]=max(h[y],h[x]+1)即可。

    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    hive 数据类型
    Hive与Hbase结合使用
    Impala介绍
    ZooKeeper管理员指南——部署与管理ZooKeeper
    hbase exporter importer 导出 导入
    Ganglia 安装 for centos6.5
    EPEL for CentOS or Redhat
    hbase->Mapreduce->hbase
    Hadoop YARN配置参数剖析(3)—MapReduce相关参数
    hadoop job 重要性能参数
  • 原文地址:https://www.cnblogs.com/--560/p/5182238.html
Copyright © 2020-2023  润新知