資料結構 可持久化並查集

2022-05-11 05:57:32 字數 1629 閱讀 2058

事實上是並查集套乙個可持久化陣列。

int a[100005];

struct segmenttree

void pushup(int o)

int buildhelp(int l, int r)

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

ls = buildhelp(l, m);

rs = buildhelp(m + 1, r);

pushup(o);

return o;

}int addhelp(int o, int l, int r, int p, ll v)

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

if(p <= m)

ls = addhelp(ls, l, m, p, v);

if(p >= m + 1)

rs = addhelp(rs, m + 1, r, p, v);

pushup(o);

return o;

}int sethelp(int o, int l, int r, int p, ll v)

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

if(p <= m)

ls = sethelp(ls, l, m, p, v);

if(p >= m + 1)

rs = sethelp(rs, m + 1, r, p, v);

pushup(o);

return o;

}int sumhelp(int o, int l, int r, int ql, int qr)

void build(int _n)

void add(int id, int pos, int val)

void set(int id, int pos, int val)

int sum(int id, int lpos, int rpos)

};struct disjointset

int find(int id, int x)

int size(int id, int x)

int merge(int id, int x, int y)

int sx = size.sum(ver[id], x, x);

int sy = size.sum(ver[id], y, y);

if(sx < sy)

find.set(ver[id], y, x);

size.add(ver[id], x, sy);

ver[++cur] = find.cur;

return x;

}} ds;

這裡預設merge操作產生乙個新的版本。並查集的ver[u]表示並查集的版本u對應線段樹的版本ver[u]

也就是說,並查集的ver[u]對應的線段樹根為find.ver[ver[u]],這裡find和size的樹根始終處於同一版本號,同步變化。

注意分清楚哪些操作產生新的版本。

假如是驗證中的例題,跳轉操作也產生新的版本,其他操作都在並查集的最後乙個版本上修改(和可持久化陣列的每個修改都帶old版本不同)。

注意並查集的最後乙個版本不見得對應線段樹的最後乙個版本,因為這裡為了節省空間使得線段樹並不會因為sum操作產生版本。

可持久化並查集

n個集合 m個操作 1 a b 合併a,b所在集合 2 k 回到第k次操作之後的狀態 查詢算作操作 3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0 所給的a,b,k均經過加密,加密方法為x x xor lastans,lastans是上一次的輸出答案 並查集實質是乙個陣列,可持久化並查...

可持久化並查集

可持久化陣列 可持久化陣列是一種可以回退,訪問之前版本的陣列 是一些其他可持久化資料結構的基石 例如可持久化並查集 與普通並查集不同的是 這裡用到了 按秩合併新增鏈結描述 include const int n 2e5 7 int rootfa n rootdep n cnt,tot struct ...

可持久化並查集

點此看題 並查集最重要的就是fafa fa陣列,我們可以拿主席樹來維護這個fafa fa,並且每次改點只需要改乙個,為保證時間複雜度我們再維護乙個dep depde p來做啟發式合併,這就變成了乙個單點修改,單點查詢的主席樹了。include include using namespace std ...