BZOJ 2151 種樹(鍊錶 貪心)

2021-08-30 08:54:58 字數 577 閱讀 1209

有一種顯然錯誤的做法:每次從堆裡取最大的,更新鍊錶

比如 19,20,19 這樣的話會先選20。但是很顯然,選兩個19帶來的貢獻可能是更好的

這時我們就要想一種能做到「反悔」的方法

其實只需要做一點點修改,每次再push乙個「19+19-20」進去,一樣是對的

那這個「19+19-20」的放在哪兒呢(編號)?只需要放在20的位置就行了,這樣是正確的

其實這樣做的本質 是重寫了這個問題 將其變成「n-2個物品中選m-1」個的形式,如此一直化歸,直到最後變成「n-2(m-1)個物品中選1個」

#include#define n 200005

using namespace std;

templateinline void read(t &x)

priority_queue>q;

int n,m,a[n],l[n],r[n],ans;

bool vis[n];

int main()

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

l[1]=n,r[n]=1;

while(m--)

cout<

bzoj 2151 種樹(貪心)

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

bzoj 2151 種樹 思路 鍊錶

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

題解 bzoj 2151 種樹

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