資料結構 Treap的實現與應用

2022-08-15 06:36:15 字數 2921 閱讀 2107

treap的本質是一顆二叉查詢樹,只是在每個結點上都附加了乙個優先順序的資訊。保證每個點的優先順序都比左右兒子小,利用優先順序,我們可以把這顆樹看成乙個小根堆。

treap樹在隨機給優先順序的情況下,可以在期望o(logn)的時間複雜度裡完成:

以上四種操作。

那麼話不多說,先上模板。這裡準備了兩個模板,第乙個來自紅書,**量89行(有三個冗餘函式居然還短些),第二個據說來自劉汝佳的《訓練指南》,**量99行但是變數名比較短,或許打起來可以更快些。

第乙個模板:

#include 

using

namespace

std;

const

int maxnode = 444444;

const

int inf = 0x3f3f3f3f;

struct treap

void update(int x)

void rotate(int &x, int t)

void __insert(int &x, int k) else

}} else

update(x);

}void __erase(int &x, int k) else

int t = priority[childs[x][0]] > priority[childs[x][1]];

rotate(x, t);

__erase(x, k);

}} else

update(x);

}int __getkth(int &x, int k)

k -= size[childs[x][0]] + cnt[x];

if(k <= 0)

return __getkth(childs[x][1], k);

}void insert(int k)

void erase(int k)

int getkth(int k)

};int main()

注釋詳見紅書190頁。

第二個模板:

#include

#include

#include

#include

using

namespace

std;

struct node

int cmp(int x)

void maintain()

}; //root全域性使用的話可以在這裡跟上*root

void rotate(node* &o,int d)

void insert(node* &o,int x)//o子樹中事先不存在x

o->maintain();

}void remove(node* &o,int x)

else

}else remove(o->ch[d],x);

if(o) o->maintain();//之前o存在,但是刪除節點後o可能就是空null了,所以需要先判斷o是否為空

}//返回關鍵字從小到大排序時的第k個值

//若返回第k大的值,只需要把ch[0]和ch[1]全互換就可以了

int kth(node* o,int k)

//返回值x在樹中的排名,就算x不在o樹中也能返回排名

//返回值範圍在[1,o->s+1]範圍內

int rank(node* o,int x)

int main()

int v;

while(scanf("%d",&v)==1)

}return

0;}

個人更加喜歡第二個模板,並用它ac了一道模板題:poj 2985

簡要題意:有n只貓,開始每只貓都是乙個小組,下面要執行m個操作,操作0 i j 是把i貓和j貓所屬的小組合併,操作1 k 是問你當前第k大的小組大小是多少. 且k<=當前的最大組數。

思路:並查集+treap,並查集維護集合合併,treap負責查詢第k大。可以只把合併後的組扔到treap裡,做乙個優化。

ac**:

#include

#include

#include

#include

#include

using

namespace

std;

struct node

int cmp(int x)

void maintain()

} *root;

void rotate(node* &o,int d)

void insert(node* &o,int x)//o子樹中事先不存在x

o->maintain();

}void remove(node* &o,int x)

else

}else remove(o->ch[d],x);

if(o) o->maintain();//之前o存在,但是刪除節點後o可能就是空null了,所以需要先

判斷o是否為空

}//返回關鍵字從小到大排序時的第k個值

int kth(node* o,int k)

//返回值x在樹中的排名,就算x不在o樹中也能返回排名

//返回值範圍在[1,o->s+1]範圍內

int rank(node* o,int x)

const

int maxn = 2e5 + 5;

int far[maxn], rnk[maxn], siz[maxn];

int find(int x)

void unite(int x, int y)

int main()

root = null;

while(m--) else

}return

0;}

據說這道題可以用樹狀陣列來a,而且**比treap短,我再去學習一波~

資料結構 Treap的實現與應用

treap的本質是一顆二叉查詢樹,只是在每個結點上都附加了乙個優先順序的資訊。保證每個點的優先順序都比左右兒子小,利用優先順序,我們可以把這顆樹看成乙個小根堆。treap樹在隨機給優先順序的情況下,可以在期望o logn 的時間複雜度裡完成 以上四種操作。那麼話不多說,先上模板。這裡準備了兩個模板,...

資料結構 Treap

前兩天看了byvoid大神寫的treap的 中幾乎給出了所有的 不過最後一部提到了乙個優化,就是對於重複的元素採用在同乙個節點中記錄乙個weight來記錄者個元素使用了多少次的寫法,以及查詢第k個數的功能的實現,我試著寫了乙個,表示樹旋轉之後需要重新設定size有一點點煩。因為找不到合適的題目去測試...

資料結構之Treap

1.概述 同splay tree一樣,treap也是乙個平衡二叉樹,不過treap會記錄乙個額外的資料,即優先順序。treap在以關鍵碼構成二叉搜尋樹的同時,還按優先順序來滿足堆的性質。因而,treap tree heap。這裡需要注意的是,treap並不是二叉堆,二叉堆必須是完全二叉樹,而trea...