可持久化 板子

可持久化并查集

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

#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;
}

可持久化平衡树

思路:在写\(\text{fhqtreap}\)\(\text{merge}\)\(\text{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\n",frank(root[i],x)-1);
        else if(op==4) printf("%d\n",Rank(root[i],x+1));
        else if(op==5) printf("%d\n",Rank(root[i],frank(root[i],x)-1));
        else printf("%d\n",Rank(root[i],frank(root[i],x+1)));
    }
    return 0;
}

2018.12.12

猜你喜欢

转载自www.cnblogs.com/ppprseter/p/10110161.html