題解 bzoj 2151 種樹

2022-05-06 21:36:10 字數 876 閱讀 6986

題意

傳送門以下是蒟蒻的做法:建立乙個大根堆a維護最大價值裡面存入它的編號以及價值。聽說配對堆可以不用定義結構體,但我不會呀!l表示這個位置左邊的編號,r同理。乙個陣列book標記是否可以選擇,每次選完之後左右兩邊進行標記,堆中加入左右之和減去本身的值再將其放入原來的位置,即可達到後悔操作,更新左右編號,然後取m次即可。

#includeusing namespace std;

int n,m,add,k;

struct nodea[200010];

int c[200010];

int l[200010],r[200010];

bool book[200010];

long long ans;

void shiftdown(int x)

}int main()

for(int i=1;i<=n;++i)

l[1]=n,r[n]=1;//環形的

ans=0;

while(m--)

ans+=val;

c[x]=c[l[x]]+c[r[x]]-c[x];//左右減去本身

book[l[x]]=1;//標記

book[r[x]]=1;

l[x]=l[l[x]];//新的左邊的原來左邊的左邊

r[x]=r[r[x]];//大體同上

r[l[x]]=x;//左邊的右邊更新

l[r[x]]=x;//右邊的左邊更新

a[++add].data=c[x];

a[add].num=x;//放入元素

shiftup(add);

} printf("%lld",ans);

return 0;

}

bzoj 2151 種樹(貪心)

題目 分析 原型是bzoj 1150 ctsc 2007 首先dp無法下手,想到貪心。想到貪心的第一感覺就是從大的開始取,但明顯有反例,最煩的就是乙個大的旁邊旁邊兩個也很大,導致如果取了那兩個最後結果更大。解決的辦法就是每次取最大的同時,把它同旁邊兩個點合併成乙個點,權值取 左 右 中間,然後後面繼...

BZOJ 2151 種樹(鍊錶 貪心)

有一種顯然錯誤的做法 每次從堆裡取最大的,更新鍊錶 比如 19,20,19 這樣的話會先選20。但是很顯然,選兩個19帶來的貢獻可能是更好的 這時我們就要想一種能做到 反悔 的方法 其實只需要做一點點修改,每次再push乙個 19 19 20 進去,一樣是對的 那這個 19 19 20 的放在哪兒呢...

bzoj 2151 種樹 思路 鍊錶

題目 先都放進堆裡取最大的,但選了乙個就不能選它兩邊的,所以可能不是最優,要有 反悔 的措施 可以取出乙個後把它兩邊的位置 l,r 在鍊錶中刪除,然後再加入乙個元素 a x a l a r a x 如果日後選了這個元素,就表示 反悔 了,當初不選 x 而是同時選了兩邊的 同時選比只選乙個或不選更優 ...