bzoj 2151 種樹 思路 鍊錶

2022-05-12 10:36:24 字數 1031 閱讀 3598

題目:

先都放進堆裡取最大的,但選了乙個就不能選它兩邊的,所以可能不是最優,要有「反悔」的措施;

可以取出乙個後把它兩邊的位置 l,r 在鍊錶中刪除,然後再加入乙個元素 a[x] = a[l] + a[r] - a[x],如果日後選了這個元素,就表示「反悔」了,當初不選 x 而是同時選了兩邊的(同時選比只選乙個或不選更優);

而此時這個 x 的兩邊實際上是 l-1 和 r+1,因為其實選的是 l,r,這點用鍊錶刪除和查詢就可以體現,更何況兩邊也可能被這樣合併過;

再記乙個 vis 表示這個位置從堆裡取出時能不能選了,和鍊錶的刪除一致;

因為每次取出都會增加乙個選擇的位置,所以取出 m 次即可。

**如下:

#include#include

#include

#include

#include

using

namespace

std;

intconst xn=2e5+5

;int

n,m,a[xn],pr[xn],nt[xn],ans;

bool

vis[xn];

structn};

priority_queue

q;int

rd()

while(ch>='

0'&&ch<='

9')ret=(ret<<3)+(ret<<1)+ch-'

0',ch=getchar();

return f?ret:-ret;

}void del(int x)

intmain()

); }

if(n<2*m)

for(int i=2;i1,nt[i]=i+1

; pr[

1]=n; nt[1]=2; pr[n]=n-1; nt[n]=1;

for(int i=1;i<=m;i++));}

printf(

"%d\n

",ans);

return0;

}

BZOJ 2151 種樹(鍊錶 貪心)

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

bzoj 2151 種樹(貪心)

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

題解 bzoj 2151 種樹

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