不需要旋轉, 只需要** \(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值來維護平衡,把每個點按照小...