P3402 模板 可持久化並查集

2021-08-31 07:29:31 字數 1529 閱讀 3419

其實看看**自己就可以懂。

注意: 1.並查集不壓縮路徑,壓縮了就回不到壓縮之前的狀態了。

2.並查集合並時,小的往大的合併,啟發式合併。

3.對於第i步(不管什麼操作)操作都要把root[i] = roo[i-1]//我在合併時,如果兩個祖先一樣就直接continue了,沒把root[i]賦值為root[i-1],一直沒看出來,拖了乙個多月才過。。。。

#include#includeusing namespace std;

int n, m, tot, fa[4000005], siz[4000005], root[200005], ls[4000005], rs[4000005];

int build(int o,int l,int r)

int mid = (l + r) >> 1;

ls[nd] = build(o*2, l, mid);

rs[nd] = build(o*2+1, mid+1, r);

return nd;

}int qurey_fa(int o, int l, int r, int pos)

int find(int x,int bb)

int qurey_size(int o, int l, int r, int pos)

int modify_fa(int o, int l, int r, int pos, int val)

int mid = (l + r) >> 1;

if(pos <= mid) ls[nd] = modify_fa(ls[o], l, mid, pos, val);

else rs[nd] = modify_fa(rs[o], mid+1, r, pos, val);

return nd;

}int modify_size(int o, int l, int r, int pos, int val)

int mid = (l + r) >> 1;

if(pos <= mid)ls[nd] = modify_size(ls[o], l, mid, pos, val);

else rs[nd] = modify_size(rs[o], mid+1, r, pos, val);

return nd;

}int main()

//如果祖先一樣,continue;

int s1 = qurey_size(root[i-1],1,n,r1);

int s2 = qurey_size(root[i-1],1,n,r2);//詢問大小

if(s1 < s2)//啟發式合併。小合大,我規定r1大

root[i] = modify_fa(root[i-1],1,n,r2,r1);//把r2的爸爸改為r1,只改r2.

root[i] = modify_size(root[i],1,n,r1,s2);//把r1並查集的大小加上r2並查集的大小

}else if(a == 2) //回到操作b。

else

}return 0;

}

P3402 模板 可持久化並查集

今天看到這道題,忽然不知道為何要線段樹了 笑 出現了一些瞎搞的想法 然後就想到了操作樹。就是,我們可以離線,然後每個位置直接維護乙個棧,記錄歷史資訊。然鵝我也不知道為什麼常數很大 include define r register int using namespace std namespace ...

洛谷P3402 模板 可持久化並查集

n個集合 m個操作 1 a b 合併a,b所在集合 2 k 回到第k次操作之後的狀態 查詢算作操作 3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出05 6 1 1 2 3 1 2 2 03 1 2 2 13 1 210 1 1 le n le 10 5,1 le m le 2 times...

洛谷 P3402 可持久化並查集

解題思路 可持久化並查集也就是可持續化線段樹 並查集 主席樹 並查集 像我們平常做的並查集都是路徑壓縮,但因為要保證可持續化,所以資訊不能改變,所以我們採用啟發式合併來合併集合。啟發式合併的樹最高深度不會超過log n 1。因為深度為2的樹需要兩個點,那麼深度為3的需要兩個深度為2的也就是2 2 4...