洛谷模板題
一聽左偏樹這個名字就感覺左偏。。
左偏樹是什麼,好像就是個堆,大根堆或小根堆,可以支援合併,取堆頂元素,刪除堆頂元素,插入元素的操作。
一些說明:
左偏樹節點除了應有的東西,還有鍵值和距離,鍵值用於比較大小,距離是什麼?
距離是這樣定義的:
節點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 3view code4using
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 }
左偏樹 模板
神經病也可以寫成右偏樹 具體左偏指左節點的距離 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 並不意味著深度,跟深度無關。講了這麼久...