可持久化並查集總結

2022-01-30 12:29:27 字數 2176 閱讀 1618

標籤: 資料結構——可持久化——可持久化並查集

閱讀體驗:

其實看起來很高大上,最後還不是淪為被我這種菜雞都能學會的東西

嗯,我只是想解釋這個並不是很難。。。連我這麼弱都。。。

然後還是以模板題為背景將比較好。。。洛谷題目傳送門

其實可持久化並查集就是要支援回到以前的版本(模擬可持久化\(陣列/線段樹\)之類的)

那麼我都模擬了,很顯然就是用主席樹來維護吧

我們以前學的主席樹是不是可以支援讓當前維護的陣列回到之前的任一版本

那我們的並查集需要維護什麼? 沒錯,\(fa\)陣列

是不是我們知道了每乙個版本的\(fa\)陣列就相當於知道了這個版本的並查集?

那麼問題轉化成了用主席樹維護乙個\(fa\)陣列對吧。。。

這個是主席樹的板子

對於並查集,它的修改是合併兩個獨立的並查集

考慮如何合併

很顯然不可以路徑壓縮(其實好像可以,只是我不會,反正這種方法也很優秀)

那麼在不路徑壓縮的情況下怎麼保證複雜度呢

嗯,普通的並查集有兩種優化,路徑壓縮和按秩合併對吧

現在路徑壓縮用不了(我不會),那就考慮按秩合併(不會可以點一下上面的鏈結)

它可以把複雜度優化到log級別(因為樹高控制了。。。)

那不就比較顯然了。。。

update(修改):查詢兩點的父親,如果不在乙個並查集,看樹高,小的合併向大的(按秩合併),合併的話就是直接主席樹板子修改\(fa\)權值就ok

query(查詢):這個直接查詢,然後可持久化的版本轉化就直接套版子做就行了

我學的時候為了複習用寫了注釋

居然 派上用場了 (≧▽≦)/啦啦啦

#include#include#include#include#include#include#include#include#include#include#include#define lst long long

#define ldb long double

#define n 200050

#define lson ljl[now].ls

#define rson ljl[now].rs

using namespace std;

const int inf=1e9;

int read()

while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();

return m?-s:s;

}int n,q,tot;

int dep[n*30],fa[n*30];

int edi[n];//版本編號

struct treeljl[n*30];

//主席樹部分

void build(int &now,int le,int ri)

//並查集初始化

int mid=(le+ri)>>1;

build(lson,le,mid),build(rson,mid+1,ri);

}void update(int &now,int pre,int le,int ri,int loc,int ff)

//當前版本,上乙個版本(複製時要用),左右端點,把loc的爸爸改成ff

lson=ljl[pre].ls,rson=ljl[pre].rs;//把前面的樹「複製」過來

int mid=(le+ri)>>1;

if(loc<=mid)update(lson,ljl[pre].ls,le,mid,loc,ff);

else update(rson,ljl[pre].rs,mid+1,ri,loc,ff);

}int query(int now,int le,int ri,int loc)

//嗯,屬於可持久化並查集的特殊部分了

void add(int now,int le,int ri,int loc)

int mid=(le+ri)>>1;

if(loc<=mid)add(lson,le,mid,loc);

else add(rson,mid+1,ri,loc);

}int find_fa(int edi,int now)

int main()

if(opt==2)

if(opt==3)

}return 0;

}

可持久化並查集

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 ...