bzoj2151 種樹(堆 優先佇列 雙向鍊錶)

2022-04-30 20:51:11 字數 1183 閱讀 1959

題目傳送門:

這道題因為優先佇列不怎麼會用,而且手寫堆的**也不長,也想複習一下手寫堆的寫法……結果……wawawawaw……看來我對堆的認識還是太淺薄了……

這道題,如果沒有限制不能選相鄰的兩個位置,那就肯定是貪心地選擇m個美觀度最大的位置種樹。然而這裡加了限制,那麼我們可以注意到,如果乙個美觀度比較大的位置不被選上,一定是因為它兩邊的位置都被選了。

於是我們可以把n個美觀度壓進乙個堆裡,每次把美觀度最大的位置取出來更新答案,然後它兩邊的位置刪掉,把這個位置的美觀度修改成(左邊的美觀度+右邊的美觀度-原美觀度),就是選這個位置與選兩邊位置的權值差。

如果細節沒有打錯,然後就可以愉快地ac這道題了。

跑的慢也不會贏的**:

#include#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define inf 1<<30;

#define min(a,b) (a#define max(a,b) (a>b?a:b)ll read()

while('0'

<=c&&c<='9')

return tmp*f;

}using

namespace

std;

struct

datahp[

200010

];int l[200010],r[200010],pos[200010

];int n,m,tot=0

;void swap(int x,int

y)void add(int id,int

w)void sift(intx)}

void del(int

id)int

main()

for(i=1;i<=n;i++)add(i,read()),l[i]=i-1,r[i]=i+1

; l[

1]=n; r[n]=1

; ll ans=0

;

while(m--)

printf(

"%lld\n

",ans);

return0;

}

bzoj2151

bzoj 2151 種樹(貪心)

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

題解 bzoj 2151 種樹

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

BZOJ 2151 種樹(鍊錶 貪心)

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