可持久化并查集

Posted yyys-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化并查集相关的知识,希望对你有一定的参考价值。

模板题

可持久化就用主席树实现,学习自这篇博客

技术图片
#include<bits/stdc++.h>
#define N 4000005
using namespace std;
int read()

    int x=0,f=1;char s=getchar();
    while(s<0||s>9)if(s==-)f=-1;s=getchar();
    while(s>=0&&s<=9)x=x*10+s-0;s=getchar();
    return x*f;

int ndnum,n;
int fa[N],lc[N],rc[N],dep[N],root[N];
void build(int k,int l,int r)//维护的是fa 

    if(l==r)fa[k]=l;return;
    int mid=(l+r)>>1;
    build(lc[k]=++ndnum,l,mid);
    build(rc[k]=++ndnum,mid+1,r);

int query(int k,int L,int R,int pos)

    if(L==R) return k;
    int mid=(L+R)>>1;
    if(pos<=mid)return query(lc[k],L,mid,pos);
    else return query(rc[k],mid+1,R,pos);

int get(int k,int x)

    int now=query(k,1,n,x);
    if(fa[now]==x)return now;
    return get(k,fa[now]);

void merge(int last,int &k,int L,int R,int pos,int f)

    k=++ndnum;lc[k]=lc[last];rc[k]=rc[last];//复制 
    if(L==R)
    
        fa[k]=f;
        dep[k]=dep[last];
        return;
    
    int mid=(L+R)>>1;
    if(pos<=mid)merge(lc[last],lc[k],L,mid,pos,f);
    else merge(rc[last],rc[k],mid+1,R,pos,f);

void update(int k,int L,int R,int pos)

    if(L==R)dep[k]++;return;
    int mid=(L+R)>>1;
    if(pos<=mid)update(lc[k],L,mid,pos);
    else update(rc[k],mid+1,R,pos);

int main()

    n=read();int m=read();
    build(root[0],1,n);
    for(int i=1;i<=m;++i)
    
        int op=read();
        if(op==1)
        
            int a=read(),b=read();
            root[i]=root[i-1];
            int posx=get(root[i],a);
            int posy=get(root[i],b);
            if(fa[posx]==fa[posy])continue;
            if(dep[posx]>dep[posy])swap(posx,posy);
            merge(root[i-1],root[i],1,n,fa[posx],fa[posy]);
            if(dep[posx]==dep[posy])update(root[i],1,n,fa[posy]);
            //因为不可能出现深度相同的两个点,所以要把其中一个点深度+1,由于是深度小的合到深度大的上,所以把深度小的增加深度 
        
        else if(op==2)
        
            int x=read();
            root[i]=root[x];
        
        else
        
            int a=read(),b=read();
            root[i]=root[i-1];
            int posx=get(root[i],a);
            int posy=get(root[i],b);
            if(fa[posx]==fa[posy])printf("1\\n");
            else printf("0\\n");
        
    
 
View Code

 

以上是关于可持久化并查集的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-3673&3674可持久化并查集 可持久化线段树 + 并查集

可持久化并查集

[BZOJ 3673]可持久化并查集 by zky

半可持久化并查集

BZOJ 3674可持久化并查集加强版&BZOJ 3673可持久化并查集 by zky 用可持久化线段树破之

bzoj3674: 可持久化并查集