[模板] 可持久化并查集

Posted neworld2002

tags:

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

传送门

基于可持久化数组 = 可持久化线段树 = 主席树,使用按秩合并,并且查询操作返回点的位置,可以重复使用,能减少查询次数。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 6000005

int fa[MAXN],d[MAXN],root[MAXN];
int lson[MAXN],rson[MAXN];
int N,M,cnt = 0;

inline int read() {
    int flag = 1,num = 0; char ch = getchar();
    while(ch>'9'||ch<'0') {
        if(ch=='-') flag = -1;
        ch = getchar();
    }
    while(ch>='0'&&ch<='9') {
        num = num*10 + ch - 48;
        ch = getchar();
    }
    return num*flag;
}

void Build(int& rt,int l,int r) {
    rt = ++cnt;
    if(l==r) {
        fa[rt] = l;
        return;
    }
    int mid = (l+r) >> 1;
    Build(lson[rt],l,mid); Build(rson[rt],mid+1,r);
}

void update(int& rt,int pre,int l,int r,int x,int val) {
    rt = ++cnt; fa[rt] = fa[pre]; d[rt] = d[pre];
    lson[rt] = lson[pre]; rson[rt] = rson[pre];
    if(l==r) {
        fa[rt] = val;
        return;
    }
    int mid = (l+r) >> 1;
    if(x<=mid) update(lson[rt],lson[pre],l,mid,x,val);
    else update(rson[rt],rson[pre],mid+1,r,x,val);
}

int query(int rt,int l,int r,int x) {
    if(l==r) return rt;
    int mid = (l+r) >> 1;
    if(x<=mid) return query(lson[rt],l,mid,x);
    else return query(rson[rt],mid+1,r,x);
}

void add(int rt,int l,int r,int x) {
    if(l==r) {
        ++d[rt];
        return;
    }
    int mid = (l+r) >> 1;
    if(x<=mid) add(lson[rt],l,mid,x);
    else add(rson[rt],mid+1,r,x);
}

int find(int x,int ver) {
    int pos = query(root[ver],1,N,x);
    return x==fa[pos] ? pos : find(fa[pos],ver);
}

int main() {

    N = read(); M = read();    
    Build(root[0],1,N);

    int u,v,opt;
    for(int i=1;i<=M;++i) {
        opt = read(); u = read();
        if(opt==1) {
            v = read(); root[i] = root[i-1];
            int uu = find(u,i-1),vv = find(v,i-1);
            if(fa[uu]==fa[vv]) continue;
            if(d[uu]>d[vv]) std::swap(uu,vv);
            update(root[i],root[i-1],1,N,fa[uu],fa[vv]);
            if(d[uu]==d[vv]) add(root[i],1,N,fa[vv]);
        }
        else if(opt==2) root[i] = root[u];
        else {
            v = read(); root[i] = root[i-1];
            puts( fa[find(u,i-1)]==fa[find(v,i-1)] ? "1" : "0" );
        }
    }
    return 0;
}

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

P3402 模板可持久化并查集

洛谷P3402 模板可持久化并查集(可持久化线段树,线段树)

可持久化并查集总结

可持久化并查集

[模板] 数据结构

[bzoj] 3673 3674 可持久化并查集 || 可持久化数组