可持久化並查集我覺得就是可持久化陣列的一種應用。可持久化陣列,顧名思義,就是有歷史版本的陣列,那麼如果我們暴力修改儲存的話,修改o(n)查詢o(1),空間o(n*m),這樣肯定不可行,那麼我們發現主席樹有這樣的功能,他可以快速複製,修改o(log),查詢o(log),空間(m*log),是乙個可行的方案。然後我們可持久化f陣列維護fa,每次按照深度啟發式合併,不進行路徑壓縮,這樣能保證時間複雜度位單次o(log^2),空間複雜度為o(2*n+m*log)。我不知道為什麼不路徑壓縮,路徑壓縮是完全可以的,但是他的時間複雜度和空間複雜度似乎都不如不路徑壓縮看,而且似乎並不好打。
#include usingnamespace
std;
inline
void read(int &sum)
const
int n=200010
;struct
segment_tree*root[n],*null,*c,*mempool;
intn,m;
void* segment_tree :: operator
new(size_t)
inline
void build(segment_tree *&p,int l,int
r) build(p->ch[0],l,(l+r)>>1
); build(p->ch[1],((l+r)>>1)+1
,r);
}inline
void insert(segment_tree *&p,segment_tree *last,int pos,int key,int l,int
r)
if(pos<=((l+r)>>1))insert(p->ch[0],last->ch[0],pos,key,l,((l+r)>>1
));
else insert(p->ch[1],last->ch[1],pos,key,((l+r)>>1)+1
,r);
}inline
void update(segment_tree *p,int
pos)
else
} p->deep++;
}inline
int deep(segment_tree *p,int
pos)
else
} return p->deep;
}inline
int f(segment_tree *p,int
pos)
else
} return p->f;
}inline
int find_root(segment_tree *p,int
x)inline
void
init()
inline
void
work()
d1=deep(root[i-1],x),d2=deep(root[i-1
],y);
if(d1>d2)x^=y^=x^=y;insert(root[i],root[i-1],x,y,1
,n);
if(d1==d2)update(root[i],y);
break
;
case
2:read(a),a^=ans;
root[i]=root[a];break
;
case
3:read(a),read(b),a^=ans,b^=ans;
root[i]=root[i-1
]; x=find_root(root[i],a),y=find_root(root[i],b);
if(x==y)puts("
1"),ans=1
;
else puts("
0"),ans=0
;
break
; }
}}intmain()
BZOJ 3674 可持久化並查集
3674 可持久化並查集加強版 time limit 15 sec memory limit 256 mb submit 4051 solved 1503 submit status discuss description description 自從zkysb出了可持久化並查集後 hzwer 亂寫...
bzoj 3674 可持久化並查集)
傳送門 題解 一道可持久化並查集的裸題,板子子對了就能過 可持久化並查集是基於主席數的一種結構,可持久化並查集要求能夠訪問歷史版本,跟主席樹很像,所以可以通過主席樹維護普通並查集的fa陣列,但是由於用主席樹維護後沒有辦法用路徑壓縮,所以需要採用新的合併方式 啟發式合併,對每乙個節點增加乙個level...
bzoj 3674 可持久化並查集加強版
description 自從zkysb出了可持久化並查集後 hzwer 亂寫能ac,暴力踩標程 kuribohg 我不路徑壓縮就過了!ndsf 暴力就可以輕鬆虐!zky bzoj 3673的加強版。就沒了。include using namespace std const int n 200000 ...