模板 左偏樹

2022-03-01 12:18:15 字數 1996 閱讀 7527

洛谷模板題

一聽左偏樹這個名字就感覺左偏。。

左偏樹是什麼,好像就是個堆,大根堆或小根堆,可以支援合併,取堆頂元素,刪除堆頂元素,插入元素的操作。

一些說明:

左偏樹節點除了應有的東西,還有鍵值和距離,鍵值用於比較大小,距離是什麼?

距離是這樣定義的:

節點i稱為外節點(external node),當且僅當節點i的左子樹或右子樹為空 ( left(i) = null或right(i) = null );節點i的距離(dist(i))是節點i到它的後代中,最近的外節點所經過的邊數。特別的,如果節點i本身是外節點,則它的距離為0;而空節點的距離規定為-1 (dist(null) = -1)。一棵左偏樹的距離,指的是該樹根節點的距離。

額。。多看幾遍才看懂。

左偏樹具體有一些性質:

[性質1] 節點的鍵值小於或等於它的左右子節點的鍵值。(鍵值就是點權)——堆的性質

[性質2] 節點的左子節點的距離不小於右子節點的距離。——左偏

[性質3] 節點的距離等於它的右子節點的距離加1。(因為左偏,所以右兒子距離小)

[引理1] 若左偏樹的距離為一定值,則節點數最少的左偏樹是完全二叉樹。

[定理1] 若一棵左偏樹的距離為k,則這棵左偏樹至少有2k+1-1個節點。

[性質4] 一棵n個節點的左偏樹距離最多為ëlog(n+1)û -1。(這是什麼鬼?)

根據性質就可以理解左偏樹操作的具體步驟了。

合併a和b:1.如果有乙個樹為空就返回另乙個

2.假定root(a).w < root(b).w, 否則交換a和b,把root(a)作為新樹的根

3.合併right(a)和b, 繼續步驟2

4.由於合併之後right(a)的距離可能會變大, 如果變大就交換right(a)和left(a)

5.由於right(a)距離改變,a的距離也會變,更新dis(a) = dis(right(a)) + 1

1

//合併以 x, y 為根的堆

2 inline int merge(int x, inty)3

合併刪除堆頂元素:刪除後合併他的兩個兒子即可

1 inline int pop(int x)//

返回新合併的堆的堆頂

2

刪除取出堆頂元素:更智障

1 inline int top(int x)//

第幾個數所在堆的堆頂

2

取出還有一些操作用到了並查集,具體細節看完整**。

1 #include 2 #include 3

4using

namespace

std;56

intn, m;

7int f[100001], l[100001], r[100001], w[100001], d[100001];//

f[i]表示第i個數所在堆的堆頂

8bool b[100001];//

表示是否被刪除 9//

合併以 x, y 為根的堆

10 inline int merge(int x, int

y)11

2021 inline int pop(int x)//

返回新合併的堆的堆頂

2229

30 inline int find(int

x)31

3435 inline int top(int x)//

第幾個數所在堆的堆頂

3639

40int

main()

4157

else

5869}70

}71return0;

72 }

view code

左偏樹 模板

神經病也可以寫成右偏樹 具體左偏指左節點的距離 geq 右節點的距離 距離指離最近擁有空節點的節點的距離 乙個節點的值一定 或 leq 或 geq 或 其子節點的值 由於左偏性質,每次可以合併至右邊,維護左偏性質後就可以保證複雜度 被踩爆的板子 或者是我?include define ls lson...

模板 左偏樹

可在log複雜度合併的堆 每個節點有乙個距離,具體定義我不知道 1.滿足堆的性質 2.左子節點距離 右子節點 3.節點距離 右子節點距離加1 按照以上的性質實現merge x,y 先選出x,y中比較大的那個 大根堆為例 再拿它的右兒子和另乙個去merge,如果merge出來不符合性質2就swap一下...

模板 左偏樹

左偏樹是一棵二叉樹,也是一種可並堆,擁有堆的性質,可以像堆一樣合併。左偏樹顧名思義,有 左偏 的特點,既每個左子樹節點的 dist 一定大於等於右子樹節點的 dist 由性質2可得 t x d t t x ch 1 d 1 同時,我們需要注意左偏樹的 dist 並不意味著深度,跟深度無關。講了這麼久...