學習筆記 左偏樹

2022-09-10 08:06:13 字數 1736 閱讀 2386

左偏樹是一種能夠在支援在 $o(logn)$ 的時間複雜度內進行合併的滿足堆性質的樹,因此別名「可並堆」,具有可合併與複雜度穩定的優勢。

模板題基本概念與定義

外結點:至少有乙個兒子是空節點的節點。

$dist_x$ 表示以 $x$ 為根的子樹內到 $x$ 距離最小的外結點的距離。特別的,對於空結點,其 $dist=-1$ 

左偏樹的性質

左偏樹滿足小根堆性質(大根堆貌似也可以),即對於結點 $x$,總有 $v_x\leq v_$ 且 $v_x\leq v_$。

左偏樹滿足左偏的性質,即對於任意節點均有:$dist_\geq dist_$。

顯然的結論

$dist_x=dist_+1$。

一棵有 $n$ 個結點的左偏樹其根節點的 $dist$ 是 $o(logn)$ 的。(可以保證合併的複雜度的穩定性)

合併操作

顯然我們對於兩個堆我們會乙個乙個比較合併,複雜度與樹高正相關。顯然,如果退化成鏈,複雜度將為 $o(n)$。

這時我們左偏樹的優勢就體現出來了,由上面的結論 2,一次合併的複雜度穩定為 $o(logn)$。由左偏的性質,每次合併時,我們選擇 $dist$ 的更小的右兒子去合併,這個過程可以遞迴實現,在過程中利用 $swap$ 維護堆性質,並在合併後回溯時維護左偏的性質即可。

1

int merge(int x,inty)2

view code

刪除所在堆頂元素操作

這裡我們需要對於每個結點維護乙個 $root_x$ 表示該節點所在的堆頂元素(即所在的左偏樹根),那麼對於 $root$ 的維護,如果合併後暴力的乙個乙個跳,複雜度將退化為 $o(n)$。我們聯想到並查集,於是使用路徑壓縮,將複雜度維持在 $o(logn)$。在刪除堆頂元素時,只需要將根的左右兩棵子樹合併即可,由於均滿足左偏樹性質,所以合併完仍為左偏樹。同時記得要將刪除節點$x$ 的 $root_x$ 也指向合併後的根,以保證路徑壓縮的正確性,同時將刪除結點的資訊清空。

1

int get_root(intx)2

6void del(intx)7

view code

完整**

1 #include2

using

namespace

std;

3static inline int

read()414

return flag ? -x : x;15}

16static inline void write(int

x)17

21const

int n = 100000 + 10;22

struct

node

2326

} val[n];

27int

n,m;

28bool

inl[n];

29int

lc[n],rc[n],dist[n],root[n];

30int merge(int x,int

y)31

39int get_root(int

x)40

44void del(int

x)45

50 signed int

main()

5159

while(m--)

6070

else

7180}81

}82return0;

83 }

view code

左偏樹學習筆記

左偏樹是一種基於二叉樹的可並堆。定義乙個節點的 距離 dis xdis x disx 為它到空節點的最短路長度,左偏樹強制要求 dis lson dis rson dis ge dis dislso n d isrs on 所以 dis x di srso n 1dis x dis 1 disx d...

左偏樹 學習筆記

首先要知道左偏樹是用來幹什麼的。如果給我們兩個優先序列,然後讓我把這兩個優先佇列合併成乙個優先佇列。如果直接用堆,就是將乙個佇列裡面的數不斷彈出然後扔到另乙個佇列裡。複雜度是 o n n為佇列中數的個數。但是用左偏樹就可以做到 log n 1 n 2 ps 為了便於討論,本文所有的左偏樹均已小根樹為...

學習筆記 左偏樹

左偏樹是一種可並堆,除了堆的基本功能,最大的特點就是支援合併堆,甚至比普通堆好寫。下面敘述以小根堆為例,大根堆對稱。o log n 求乙個數所在堆的根 o 1 求最小值 o log n 合併兩個堆 o log n 刪除最小值 o log n 插入乙個數 n 是插入的總節點數 或當前堆的節點數 str...