【模板】可持久化并查集
生活随笔
收集整理的這篇文章主要介紹了
【模板】可持久化并查集
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接
題目描述
給定 nnn 個集合,第 iii 個集合內(nèi)初始狀態(tài)下只有一個數(shù),為 iii。
有 mmm 次操作。操作分為 333 種:
-
1 a b 合并 a,ba,ba,b 所在集合;
-
2 k 回到第 kkk 次操作(執(zhí)行三種操作中的任意一種都記為一次操作)之后的狀態(tài);
-
3 a b 詢問 a,ba,ba,b 是否屬于同一集合,如果是則輸出 1 ,否則輸出 0。
輸入格式
第一行兩個整數(shù),n,mn,mn,m。
接下來 mmm 行,每行先輸入一個數(shù) optoptopt。若 opt=2opt=2opt=2 則再輸入一個整數(shù) kkk,否則再輸入兩個整數(shù) a,ba,ba,b,描述一次操作。
輸出格式
對每個操作 333,輸出一行一個整數(shù)表示答案。
輸入輸出樣例
輸入 #1
5 6 1 1 2 3 1 2 2 0 3 1 2 2 1 3 1 2輸出 #1
1 0 1說明/提示
對于 100%100\%100% 的數(shù)據(jù),1≤n≤105,1≤m≤2×1051\le n\le 10^5,1\le m\le 2\times 10^51≤n≤105,1≤m≤2×105。
Solution
- 模板題,可以通過 可持久化數(shù)組 +++ 啟發(fā)式合并 /// 按秩合并 實(shí)現(xiàn)。
Code
#include<cstdio> #include<algorithm> using namespace std; const int maxn=300010; struct SegmentTree{int lc,rc,l,r,fa,siz; }tr[maxn*40]; int n,m,tot,root[maxn]; inline int build(int l,int r){int u=++tot,mid=(l+r)>>1;tr[u].l=l;tr[u].r=r;if(l==r){tr[u].fa=l;tr[u].siz=1;return u;}tr[u].lc=build(l,mid);tr[u].rc=build(mid+1,r);return u; } inline int query(int u,int a){if(tr[u].l==tr[u].r)return u;int mid=(tr[u].l+tr[u].r)>>1;if(a<=mid)return query(tr[u].lc,a);else return query(tr[u].rc,a); } inline int find(int v,int x){int p=query(root[v],x);return tr[p].fa==x?x:find(v,tr[p].fa); } inline int merge(int p,int pos,int fa){int u=++tot;tr[u].l=tr[p].l;tr[u].r=tr[p].r;if(tr[u].l==tr[u].r){tr[u].fa=fa;return u;}int mid=(tr[u].l+tr[u].r)>>1;if(pos<=mid){tr[u].rc=tr[p].rc;tr[u].lc=merge(tr[p].lc,pos,fa);}else{tr[u].lc=tr[p].lc;tr[u].rc=merge(tr[p].rc,pos,fa);}return u; } inline int add(int p,int pos,int d){int u=++tot;tr[u].l=tr[p].l;tr[u].r=tr[p].r;if(tr[u].l==tr[u].r){tr[u].fa=tr[p].fa;tr[u].siz=tr[p].siz+d;return u;}int mid=(tr[u].l+tr[u].r)>>1;if(pos<=mid){tr[u].rc=tr[p].rc;tr[u].lc=add(tr[p].lc,pos,d);}else{tr[u].lc=tr[p].lc;tr[u].rc=add(tr[p].rc,pos,d);}return u; } int main(){scanf("%d%d",&n,&m);root[0]=build(1,n);for(int i=1;i<=m;++i){int opt,a,b;scanf("%d",&opt);if(opt==1){scanf("%d%d",&a,&b);a=find(i-1,a);b=find(i-1,b);if(a==b){root[i]=root[i-1];continue;}int x=query(root[i-1],a),y=query(root[i-1],b);if(tr[x].siz>tr[y].siz)swap(x,y),swap(a,b);root[i]=merge(root[i-1],a,b);root[i]=add(root[i],b,tr[x].siz);}else if(opt==2){scanf("%d",&a);root[i]=root[a];}else{scanf("%d%d",&a,&b);root[i]=root[i-1];printf("%d\n",find(i,a)==find(i,b));}}return 0; }總結(jié)
以上是生活随笔為你收集整理的【模板】可持久化并查集的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微博头条等显示用户IP微博显示头条什么意
- 下一篇: 电脑不能进系统怎么办电脑打不开如何装系统