bzoj 3673 可持久化並查集 by zky

2021-08-23 12:03:12 字數 1063 閱讀 6081

n個集合 m個操作

操作:

1 a b 合併a,b所在集合

2 k 回到第k次操作之後的狀態(查詢算作操作)

3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0

0之前用rope水過這道題

今天來學習一下正確的可持久化並查集的姿勢

其實就是普通的並查集套上乙個支援可持久化的結構

一般大家比較熟悉的且支援可持久化的就是線段樹了

於是我們只需要把陣列寫成線段樹的形式

然後可持久化按線段樹來寫,並查集按並查集來寫就可以了

時間複雜度比正常的並查集多乙個log,感覺還是跑得挺快的

code:

#include#include#include#includeusing namespace std;

const

int n=20005;

int n,m;

int rt[n],s1[n*30],s2[n*30],c[n*30];

int num=0;

void bt (int &now,int l,int r)

intmid=(l+r)>>1;

bt(s1[now],l,mid);bt(s2[now],mid+1,r);

}int find (int

now,int l,int r,int x)

void change (int

now,int &rt,int l,int r,int x,int val)

intmid=(l+r)>>1;

s1[rt]=s1[now];s2[rt]=s2[now];

if (x<=mid) change(s1[now],s1[rt],l,mid,x,val);

else change(s2[now],s2[rt],mid+1,r,x,val);

}int find_fa (int &now,int x)

}int main()

if (op==2)

if (op==3)

}return 0;

}

bzoj3673 可持久化並查集

bzoj 我們考慮把每個操作建成乙個點 i 對於 1 和 3 操作,連邊 i 1,i 對於 2 操作,連邊 k i,i 容易發現這是一棵樹,並且並查集的操作可以回退,那麼我們直接在樹上dfs,在進入節點 回溯時處理merge split 查詢即可.時間複雜度 o m log n 超短.pragma ...

BZOJ3673 可持久並查集

可以用線段樹維護 每個葉子結點存它父親的位置 查乙個點的父親和正常並查集差不多 記錄每個點的深度 當要相連的兩個點深度相同時 p,q 把q的deep 整體用主席樹維護 copy hzwer的 orz include include using namespace std inline int rea...

BZOJ 3673 可持久化並查集 by zky

n個集合 m個操作 操作 1 a b 合併a,b所在集合 2 k 回到第k次操作之後的狀態 查詢算作操作 3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0 05 6 1 1 2 3 1 2 2 0 3 1 2 2 1 3 1 2 1 0 1可持久化並查集不好寫,我們考慮到並查集的寫法就是...