題目傳送門:
這道題因為優先佇列不怎麼會用,而且手寫堆的**也不長,也想複習一下手寫堆的寫法……結果……wawawawaw……看來我對堆的認識還是太淺薄了……
這道題,如果沒有限制不能選相鄰的兩個位置,那就肯定是貪心地選擇m個美觀度最大的位置種樹。然而這裡加了限制,那麼我們可以注意到,如果乙個美觀度比較大的位置不被選上,一定是因為它兩邊的位置都被選了。
於是我們可以把n個美觀度壓進乙個堆裡,每次把美觀度最大的位置取出來更新答案,然後它兩邊的位置刪掉,把這個位置的美觀度修改成(左邊的美觀度+右邊的美觀度-原美觀度),就是選這個位置與選兩邊位置的權值差。
如果細節沒有打錯,然後就可以愉快地ac這道題了。
跑的慢也不會贏的**:
#include#includebzoj2151#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;
}
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 的放在哪兒呢...