日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【模板】可持久化并查集

發(fā)布時(shí)間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【模板】可持久化并查集 小編覺得挺不錯的,現(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^51n1051m2×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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。