zoukankan      html  css  js  c++  java
  • 可持久化 板子

    可持久化并查集

    思路:用可持久化线段树实现可持久化数组,然后并查集按秩合并即可。注意一些实现细节。

    #include <cstdio>
    #include <algorithm>
    const int N=2e5+10;
    int ch[N*30][2],dep[N*30],f[N*30],tot,n,m,root[N],T;
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define ols ch[las][0]
    #define ors ch[las][1]
    void build(int &now,int l,int r)
    {
        now=++tot;
        if(l==r) {dep[now]=1,f[now]=l;return;}
        int mid=l+r>>1;
        build(ls,l,mid),build(rs,mid+1,r);
    }
    int query(int now,int l,int r,int p)
    {
        if(l==r) return now;
        int mid=l+r>>1;
        if(p<=mid) return query(ls,l,mid,p);
        else return query(rs,mid+1,r,p);
    }
    void changef(int &now,int las,int l,int r,int p,int d)
    {
        if(!now) now=++tot;
        if(l==r) {dep[now]=dep[las],f[now]=d;return;}
        int mid=l+r>>1;
        if(p<=mid) changef(ls,ols,l,mid,p,d),rs=ors;
        else changef(rs,ors,mid+1,r,p,d),ls=ols;
    }
    void changed(int now,int l,int r,int p)
    {
        if(l==r) {++dep[now];return;}
        int mid=l+r>>1;
        if(p<=mid) changed(ls,l,mid,p);
        else changed(rs,mid+1,r,p);
    }
    int Find(int x)
    {
        int fa=query(root[T],1,n,x);
        if(f[fa]!=x) return Find(f[fa]);
        return fa;
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("dew.out","w",stdout);
        scanf("%d%d",&n,&m);
        build(root[0],1,n);
        for(int op,a,b,i=1;i<=m;i++)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&a,&b);
                a=Find(a),b=Find(b);
                ++T;
                if(a!=b)
                {
                    if(dep[a]<dep[b]) std::swap(a,b);
                    changef(root[T],root[T-1],1,n,f[b],f[a]);
                    if(dep[a]==dep[b]) changed(root[T],1,n,f[a]);
                }
                else
                    root[T]=root[T-1];
            }
            else if(op==2)
                scanf("%d",&a),root[++T]=root[a];
            else
            {
                scanf("%d%d",&a,&b);
                puts(Find(a)==Find(b)?"1":"0");
                ++T,root[T]=root[T-1];
            }
        }
        return 0;
    }
    

    可持久化平衡树

    思路:在写( ext{fhqtreap})( ext{merge})( ext{split})的时候每次新建节点进行可持久化,注意复制空节点的情况。空间要往大开,反正只乘个(log n)是不够的

    #include <cstdio>
    #include <cstdlib>
    #define ls ch[now][0]
    #define rs ch[now][1]
    const int N=5e5+10;
    const int inf=2147483647;
    int ch[N*50][2],val[N*50],siz[N*50],dat[N*50],root[N],tot;
    int Copy(int now)
    {
        if(!now) return 0;//注意
        val[++tot]=val[now],siz[tot]=siz[now],dat[tot]=dat[now],ch[tot][0]=ls,ch[tot][1]=rs;
        return tot;
    }
    void updata(int now){siz[now]=siz[ls]+siz[rs]+1;}
    void split(int now,int k,int &x,int &y)
    {
        if(!now){x=y=0;return;}
        if(k>=dat[now])
        {
            x=Copy(now);
            split(ch[x][1],k,ch[x][1],y);
            updata(x);
        }
        else
        {
            y=Copy(now);
            split(ch[y][0],k,x,ch[y][0]);
            updata(y);
        }
    }
    int Merge(int x,int y)
    {
        if(!x||!y) return Copy(x+y);
        int now;
        if(val[x]<val[y])
            now=Copy(x),rs=Merge(rs,y);
        else
            now=Copy(y),ls=Merge(x,ls);
        return updata(now),now;
    }
    int New(int k)
    {
        dat[++tot]=k,siz[tot]=1,val[tot]=rand();
        return tot;
    }
    void Insert(int id,int k)
    {
        int x,y;
        split(root[id],k,x,y);
        root[id]=Merge(x,Merge(New(k),y));
    }
    void extrack(int id,int k)
    {
        int x,y,z;
        split(root[id],k,x,y);
        split(x,k-1,x,z);
        z=Merge(ch[z][0],ch[z][1]);
        root[id]=Merge(x,Merge(z,y));
    }
    int Rank(int now,int k)//排名为k的数
    {
        if(k<=siz[ls]) return Rank(ls,k);
        else if(k>siz[ls]+1) return Rank(rs,k-siz[ls]-1);
        else return dat[now];
    }
    int frank(int now,int k)//查询k的排名
    {
        if(!now) return 1;
        if(k<=dat[now]) return frank(ls,k);
        else return frank(rs,k)+siz[ls]+1;
    }
    int main()
    {
        int m;scanf("%d",&m);
        Insert(0,inf),Insert(0,-inf);
        for(int v,op,x,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&v,&op,&x);
            root[i]=root[v];
            if(op==1) Insert(i,x);
            else if(op==2) extrack(i,x);
            else if(op==3) printf("%d
    ",frank(root[i],x)-1);
            else if(op==4) printf("%d
    ",Rank(root[i],x+1));
            else if(op==5) printf("%d
    ",Rank(root[i],frank(root[i],x)-1));
            else printf("%d
    ",Rank(root[i],frank(root[i],x+1)));
        }
        return 0;
    }
    

    2018.12.12

  • 相关阅读:
    网站整合Discuz!NT论坛,网站用户和论坛用户统一并同步,详解(三)
    asp.net,js捕捉文本框回车键事件,兼容FF
    asp.net,C#,html控件的File控件文件上传简单实例,vs2010
    classid是“d27cdb6eae6d11cf96b8444553540000”的图片轮换代码去掉黑色边框[摘自布布分享,tech.bubufx.com]
    webform下treeview带checkbox自带控件,选择后联动事例(vs2010)
    图片固定在图片框内,大小自动适应,宽高避免拉伸
    梅花雪2.0树带checkbox取值实例(vs2010)
    asp.net上传文件使用file控件,判断文件大小,取得文件路径时报错【System.IO.FileNotFoundException:未能找到文件】的解决办法
    布布分享,js控制frame的隐藏或显示
    不但要返回顶部,还要返回底部,小改变,实用,?scroll?的js代码,支持IE,FF,chrome[摘自布布分享,tech.bubufx.com]
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10110161.html
Copyright © 2011-2022 走看看