模板 講解 Treap名次樹

2022-05-25 14:12:07 字數 2281 閱讀 4716

《題目鏈結》

學平衡樹的過程可以說是相當艱難。瀏覽blog的過程中看到大量指標版平衡樹,不擅長指標操作的我已經接近崩潰。於是,我想著一定要寫一篇非指標實現的treap的blog。

具體如下。

treap(樹堆,tree+heap)是一種強大的資料結構——每個節點除了本身鍵值(v)之外,附有乙個隨機優先順序(p),其中v滿足二叉搜尋樹性質,p滿足堆性質(下文中為大根堆),通過旋轉操作來維護性質,並使整棵樹保持平衡。

顧名思義就是可以查詢x的排名、查詢第x名的值、查詢前驅與後繼的樹。詳見標題下方題目鏈結。

struct node

;//鍵值,優先順序,(包括自身在內的)子樹大小,左右子節點。

每一種操作都是從根開始。

首先, 與插入二叉搜尋樹一樣。

給待插入節點乙個隨機的p值,為了避免重複,對生成隨機數做了一些特殊處理。

int random(void)

其次,待插入點的v到了合適的位置時,我們會發現它的p也許不符合堆性質。

這時,我們要通過旋轉操作維護堆性質。

具體操作為,以當前點為根,進行如下圖所示的旋轉。圖源網路。侵刪。

旋轉示例。圖為右旋,自繪。

旋轉後更新子樹大小。

void update(int i)

插入**。

void insert(int &i,int x)

++s[i].size;

bool t=x>s[i].v;

insert(s[i].c[t],x);

if(s[s[i].c[t]].p>s[i].p)

rotate(i,!t);

}

其實就是完全把插入的操作反過來。

待刪除的v大於當前點的v時,遞迴右子樹刪除當前點;

否則,遞迴左子樹刪除當前點。

操作完畢後更新當前點的子樹大小。

void erase(int &i,int x)

else

else

erase(s[i].c[x>s[i].v],x);

update(i);

}

int rank(int i,int x)

int xth(int i,int x)

查詢x的前驅,即查詢整個treap中比x小的最大數

int pre(int i,int x)

和查詢前驅完全相反。

#include #include #include #include #include using namespace std;

const int maxn=100010,inf=10000010;

int n;

class treap

void insert(int &i,int x)

++s[i].size;

bool t=x>s[i].v;

insert(s[i].c[t],x);

if(s[s[i].c[t]].p>s[i].p)

rotate(i,!t);

} void erase(int &i,int x)

else

else

erase(s[i].c[x>s[i].v],x);

update(i);

} int rank(int i,int x)

int xth(int i,int x)

int pre(int i,int x)

int next(int i,int x)

{ return i ? (x

模板這種東西,尤其是**量大的,及時複習很重要。

希望我的講解可以幫助到大家吧。

謝謝閱讀。

Treap實現的名次樹

1.感覺之前邵叔叔教的做fib的那個支援刪除 其實刪除只是打標記,而且不支援插入。和查詢的排序二叉樹就是個靜態的名次樹嘛。我居然學到了這麼奇怪的資料結構。2.寫的時候坑了幾次 1 不要亂用引用,getkth裡那個引數o沒過腦子用了引用,結果把樹搞爛了,一堆ch x 賦值成null了。2 寫查詢的時候...

平衡樹模板 Treap

演算法標籤 treap 種下第一棵平衡樹 這是一道模板題。如果覺得這個題水的可以做一下4544壓行,是千古神犇花爸爸出的神犇題。您需要寫一種資料結構 可參考題目標題,但是這句話其實並沒有什麼用233 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3....

模板 普通平衡樹 Treap

題目描述 您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3.查詢x數的排名 排名定義為比當前數小的數的個數 1。若有多個相同的數,因輸出最小的排名 4.查詢排名為x的數 5.求x的前驅 前驅定義為小於x,且最大的...