當平衡樹需要可持久化的時候,意味著我們需要訪問以前的某個時間點的平衡樹,就要保持以前的樹形態不變,新建乙個時間戳,構建一棵新的樹。
如果用以前的旋轉treap可能就不方便做到(又要打時間戳,又要新建節點,又要旋轉),而且涉及到旋轉,空間可能會承受不住,我們需要用到一種新的平衡樹——fhq treap
這是一種非常好寫的treap 核心操作有兩個,乙個是split乙個是merge。
split(node,k,x,y) 意思是把以node為跟的子樹分成兩部分,一部分小於等於k(根為x),一部分大於k(根為y)。在可持久化的時候要保證以前的樹的形態不變,就要每一次copy乙個節點過來。
而我們每一次遞迴只會訪問乙個節點的左右子樹中的乙個節點,又因為treap的均攤深度為log,所以總體的空間為nlogn,是非常高效的。
說完split接下來是merge
merge函式,是有返回值的,merge(x,y) 是把以x為根的子樹和以y為根的子樹合併起來,返回這棵新的樹的根,遞迴的實現,非常好懂。
接下來的所有操作都是基於以上兩個核心的操作,非常好理解,比旋轉的treap好理解而且更好寫,注意可持久化即可。
——by vane
1 #include2using
namespace
std;
3const
int n=500005;4
struct
node
5t[n*50];9
int root[n],cnt=1;10
int copynode(int
x)11
16void update(int
cur)
1721
int newnode(int
val)
2230
void split(int now,int k,int &x,int &y)
3140
else
4145
update(x);
46update(y);47}
48}49int merge(int x,int
y)50
59else
6066}67
void insert(int bb,int
val)
6875
void delete(int bb,int
val)
7683
int getpos(int now,int
k)8491}
92int getkth(int bb,int
val)
93100
int getval(int now,int
k)101
106int getpre(int bb,int
val)
107116
int getnext(int bb,int
val)
117124
intmain()
125141
}142 }
可持久化Treap
本來是想寫一點題的,但是hfu最近讓我改鍵盤指法,原來都是亂打 手速蠻快就是錯的多 剛開始練手法真的煩躁,像我這種從來不用小指頭的 就寫個學習筆記吧.非教程向,只是懂了後寫點隨筆,練成指法說不定能來填坑.可持久化treap首先是基於非旋轉式treap的,如果要旋轉的話那麼就會破壞父子關係導致無法可持...
可持久化Treap
可持久化treap本質上市乙個二叉平衡樹,若不對其規則進行修改,中序遍歷後得出的序列是遞增的。void maintain o 計算結點o的size int lowcount key 比key所在位置小1 int uppercount key key所在的位置,如果有多個相同的key,選位置最大的 i...
LOJ 持久化序列 可持久化treap
一道模板題 在寫完這道題以後就去找其他帶翻轉的可持久化treap題去寫了 發現自己根本不會可持久化treap 什麼標記翻轉可持久化 自閉了一整天 網上也沒有找到很好的模板 於是選擇擱置一段時間 等以後時間充裕了再來磕 includeusing namespace std const int maxn...