學習筆記 fhq treap

2022-09-17 07:33:07 字數 2446 閱讀 5996

不需要旋轉, 只需要** \(split\) 和合併 \(merge\),就可以支援 \(splay\) 的所有操作。

非常好寫,非常好調。

並且支援可持久化(雖然我不會)。

對於每個點需要乙個附加權值,根據這個附加權值維護乙個小根堆,這樣這棵樹平衡與否是由這個附加權值決定的,那麼這個權值該怎麼取呢?隨機!

這樣 \(treap\) 就大概是平衡的了。

\(treap\) 還滿足左子 \(<\) 根 \(<\) 右子。

把乙個 \(treap\) 分成兩個,按權值分,把 \(\le v\) 的分在左子樹,把 \(> v\) 的分在右子樹。

void split(int p, int v, int &x, int &y)

if(val[p] <= v) x = p, split(ch[p][1], v, ch[p][1], y); //如果根的權值<=v,就在右子樹中split

else y = p, split(ch[p][0], v, x, ch[p][0]); //否則在左子樹中split

pushup(p);

}

把兩個 \(treap\) 合成乙個,這裡就需要用附加權值來保證 \(treap\) 平衡。

int merge(int x, int y)

else //否則,把x合併到y的左子樹中

}

以上就是 fhq treap 的兩個基本操作,接下來考慮如何使用。

以洛谷p6136 【模板】普通平衡樹(資料加強版)為例。

以 \(v\) 為權值**split(rt, v, x, y),然後新建乙個權值為 \(v\) 的點,再合併merge(merge(x, newnode(v)), y)

int newnode(int v)

void insert(int v)

void delete(int v)

以 \(v\) 為權值**,排名就是 \(v\) 的左子樹的大小 + 1。

int get_rank(int v)

跟線段樹分治差不多?

如果左子樹大小 \(≥ k\),就在左子樹中找排名為k的,否則在右子樹中找排名為k - siz[ch[p][0]] - 1的。

如果當前排名正好為 \(k\),就直接返回。

int kth(int p, int k)

博主用了遞迴寫法,也可以用while()

以 \(v\) 為權值**,\(v\) 的前驅即為左子樹的最後乙個,也就是排名為siz[x]的。

int get_pre(int v)

同樣以 \(v\) 為權值**,後繼即為右子樹的第乙個,也就是排名為1的。

int get_nxt(int v)

注意每次 split 都要記得 merge 不然複雜度無法保證

放一下完整**

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

const int n = 2e6;

int n, m;

int read()

int rt, cnt, siz[n], ch[n][2], dat[n], val[n];

void pushup(int p)

int newnode(int v)

int merge(int x, int y)

else }

void split(int p, int v, int &x, int &y)

if(val[p] <= v) x = p, split(ch[p][1], v, ch[p][1], y);

else y = p, split(ch[p][0], v, x, ch[p][0]);

pushup(p);

}void insert(int v)

void delete(int v)

int get_rank(int v)

int kth(int p, int k)

int get_pre(int v)

int get_nxt(int v)

int main()

int lst = 0, ans = 0;

while(m--)

printf("%d\n", ans);

return 0;

}

學習筆記 FHQ Treap

fhq treap 發明者範浩強年年noi金牌 是一種神奇的資料結構,也叫非旋treap,它不像treap zig zag搞不清楚 所以叫非旋嘛 也不像splay完全看不懂,而且它能完成treap與splay能完成的所有事,短,理解也容易。fhq treap和treap很像,都是給每個節點乙個隨機的...

Fhq Treap 學習筆記

fhq treap 是一種平衡樹,又稱非旋 treap,其特點可以從名字裡明顯看出。fhq treap 具有 短 拓展性強的優點,在 oi 中的用途較廣。對於插入 v 的操作,我們把 treap 拆成 leq v 1 和 geq v 兩部分,接下來把 v 和 leq v 1 的部分合併,再把這一部分...

fhq treap(無旋treap) 學習筆記

首先最好要會寫treap 也先了解一下笛卡爾樹是什麼。fhq treap和treap同樣有乙個隨機分配的rnd值,用於平衡,但fhq treap不需要旋轉操作來維持平衡,因為有兩個神奇的操作merge和split 在兩種操作之前,要明確的一點是fhq treap依靠rnd值來維護平衡,把每個點按照小...