[模板] 可持久化并查集
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;
}
以上是关于[模板] 可持久化并查集的主要内容,如果未能解决你的问题,请参考以下文章