一種好用的資料結構,支援插入(\(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這對好 ...