關於Treap平衡樹的一點總結

2022-06-08 08:39:10 字數 1770 閱讀 8780

一種好用的資料結構,支援插入(\(insert\)),刪除(\(remove\)),查前驅(\(pre\))後繼(\(suf\)),查樹的排名(\(get rank by val\)),據排名查數(\(getvalbyrank\))。

二叉樹,點帶權,左子樹上的點都比根小,右子樹上的點都比根大。

但是,如果插入的是乙個單調的序列,每次對樹進行檢索操作都是\(o(n)\) ,總複雜度變成\(o(n^2)\) ,不能接受。

這是treap的核心操作。通過對原\(bst\)樹進行旋轉操作,使樹的高度減小,形狀更平衡

那麼,什麼樣的操作才是合理的旋轉操作呢?由於普通的\(bst\)在隨機的資料下是趨近平衡的,所以我們給每個點乙個隨機權值,滿足大根堆性質,盡量平衡數。

把\(p\)的左子節點繞著\(p\)向右旋轉。

inline void zig(int &p)
左旋同理。

初始狀態設為乙個\(inf\) ,乙個\(-inf\) ,防止溢位。

根節點編號設為\(1\) ,初始權值為\(inf\)

記得先新建\(-inf\) ,因為我是初始化根和根的右節點

我就是因為忘了\(build\)才多調了半小時

inline void build()
inline int getrank(int p,int val)
inline int getval(int p,int rank)
如果以前沒有這個點-->新建

如果以前有這個值了-->\(cnt++\)

inline void insert(int &p,int val)

if(val==t[p].val)

if(valt[p].val)

if(t[p].l||t[p].r)

else p=0;

return;

} val\(pre\):左子樹上一直往右找

\(suf\):右子樹上一直往左找

注意邊界條件。

#include#define n (400010)

#define inf (998244353)

using namespace std;

struct xbkt[n];

int n,tot,rt;

inline int read()

while(ch>='0'&&ch<='9')

return f?-w:w;

}inline int new(int val)

inline void update(int p)

inline void build()

inline int getrank(int p,int val)

inline int getval(int p,int rank)

inline void zig(int &p)

inline void zag(int &p)

inline void insert(int &p,int val)

if(val==t[p].val)

if(valt[p].val)

if(t[p].l||t[p].r)

else p=0;

return;

} valupdate(p);

return;

}int main()

return 0;

}

平衡樹Treap模版的總結

自己總結的乙個平衡樹treap模版,自己測試了一下,感覺沒什麼錯誤,但總感覺有bug,請大家指教一下,下面是自己測試時寫的測試用的 請無視 include include include include include using namespace std typedef long long ll...

關於MongoDB的一點總結

今天推送引擎註冊在dubbo上的服務總是自動會關閉掉,查了一下發現是system.in.read 的原因,導致自動關閉。但是還是不太明白,別人執行spring的時候,只要啟動以後就不會自動關閉,而我的spring剛啟動就關閉了,找了半天都沒有解決,沒辦法,只好用了最笨的方法 while true 而...

關於演算法的一點總結

分解問題的角度 fix 某一維度,嘗試另一維度上的所有可能 a.可能是array的 i,j pointers,b.可能是矩形的長與寬,c.可能是tree的每乙個subtree,d.可能是情景題的每一對pair 求所有解的,暴力上backtracking吧 如果問最短 最少的,先想bfs dp這對好 ...