左偏樹 可以標記合併的堆

2022-02-06 03:21:36 字數 1533 閱讀 6350

左偏樹:

左偏樹(leftist tree)是一種可並堆的實現。左偏樹是一棵二叉樹,它的節點除了和二叉樹的節點一樣具有鍵值外,還有乙個屬性距離(dist)。

距離指的是這個點到某個葉子結點的最短距離

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

[性質2] 節點的距離等於它的右子節點的距離加1。(顯然)

——sd_le

優點:支援堆的logn合併,還可以打標記。

1.模板:

int mer(int x,int

y)void pop(int

x)

所有的操作,都是在mer的支援下進行的。

複雜度證明:

因為每次都是對右子樹進行合併,不斷走右子樹,由於左子樹的距離大於等於右子樹的距離,所以複雜度logn

例題:2.bzoj 2809: [apio2012]dispatching

n個點組成一棵樹,每個點都有乙個領導力和費用,可以讓乙個點當領導,然後在這個點的子樹中選擇一些費用之和不超過m的點,得到領導的領導力乘選擇的點的個數(領導可不被選擇)的利潤。求利潤最大值。

n≤100000 ;

從葉子節點開始,每個點開始是乙個大根堆,堆裡的就是這個點的人。

往父親那裡合併堆,記錄堆的大小,費用的總和。

從兒子合併完畢後,在每個節點,不斷踢出費用最大的人,直到費用的總和<=m 這就是這個點的最優方案了。(顯然,花費最小的都留下了)

對於每個點,用這個點的領導力乘堆的大小嘗試更新答案即可。

注意:和子樹合併的時候,rt[x]=mer(rt[x],rt[y]) 注意是rt[y]因為這才是y的所屬堆的入口。

**:

#includeusing

namespace

std;

typedef

long

long

ll;const

int n=100000+10

;int

n;ll m;

ll c[n],p[n];

intrt[n];

ll siz[n];

ll ans;

struct

nodee[

2*n];

inthd[n],cnt;

void add(int x,int

y)struct

trz[n];

void pushup(int

x)int mer(int x,int

y)int split(int

x)void dfs(int x,int

fa)

while(z[rt[x]].sum>m&&z[rt[x]].siz)

ans=max(ans,z[rt[x]].siz*p[x]);

}int

main()

dfs(

1,0);

printf(

"%lld

",ans);

return0;

}

當要用到合併,打標記的堆的時候,就可以考慮左偏樹。

資料結構 可合併堆 左偏樹

剛剛又看了一遍左偏樹的內容,為了加深理解,自己也寫一篇,夾雜著許許多多的借鑑。左偏樹是可合併的二叉堆,首先滿足所有的堆的性質,其外,它還可以合併。左偏樹的樹節點需要儲存的資訊有 1.左右子樹節點編號 2.此節點到有空子結點的結點的最短距離 len 3.自身權值 首先解釋一下什麼是有空子節點的節點,就...

堆之左偏樹

左偏樹 左偏堆 優勢 兩個左偏樹合併效率高o logn 外結點 乙個結點的孩子數不滿兩個,就稱之為外結點。距離 dist 每個節點上有個距離 dist 的屬性,dist的值為該結點到最近的外結點所經過的邊的個數。外結點的dist 0。空結點的dist 1。左偏樹定義 1.是一顆二叉樹。2.是個堆。3...

左偏樹(可並堆)

左偏樹其實是一種可並堆,它可以 o log2 n o l og2n 合併兩個堆。那左偏?也就是說他左邊肯定有什麼東西比右邊大 別著急,在左偏樹上有乙個叫距離的東西 個點的距離,被定義為它子樹中離他最近的外節點到這個節點的距離 這與樹的深度不同 其中我們定義乙個節點為外節點,當且僅當這個節點的左子樹和...