洛谷P1484種樹 貪心 大根堆 雙向鍊錶

2021-09-24 18:00:49 字數 1528 閱讀 2471

題目:

分析:一、採用貪心演算法。

以下面樣例說明:

1 6 10 9 -1 4

第一步:所有權值push到優先佇列,彈出最大值10,它的id是3,第一棵樹種在3號位,記ans=10。

第二步:但觀察發現兩棵樹時應該分別種在2,4位,這裡存在「後悔」——第一棵樹的位置不對。我們在完成第一步後把3號位左右兩位合併成一棵樹,權值為6+9-10 (為什麼要-10,是因為ans已經賦值為10,需要抵消),將新的權值5 push入優先佇列,(別擔心,我們把6與9對應的第2,4位做上標記,等會在優先佇列裡碰到有標記的直接彈出,從而實際上)此時隊首權值是5,彈出,記ans=10+5,從而實際兩棵樹種在2、4位。對於另一種樣例:

1 6 10 9 -1 8

第一步中ans=10,第二步中因為新的隊首是8,則記ans+=8,從而ans=18。兩棵樹種在3、6位。

二、因為三個位置的權值合併成乙個新的位置,所以需要引入雙向鍊錶。

三、需要注意的是,這三個位置的左端與右端,仍保留在優先佇列裡,但彈出時不能加到ans裡,所以引入標記變數***,如果標為1,則直接彈出。

四、關於《優先佇列+結構體內過載比較函式》,請參見我寫的部落格

【手工模擬說明】

以此例說明:

6 31 6 10 9 -4 8

step1:種一棵樹時,當前最優選10,得ans=10,然後把它前後染色,得:

1 6(s) 10 9 (s) -4 8(用到大根堆,碰到有標記s的直接彈出)

再把「後悔樹」種進去,相當於變成:

1 5 -4 8

step2:種第二棵時,當前最優選8,得ans=10+8,然後把它前後染色,再把「後悔樹」種進去,相當於變成:

1 5 -12

step3:種第三棵樹時,當前最優選5,得ans=10+8+5,然後把它前後染色,再把「後悔樹」種進去,相當於變成:

-16

從上面模擬過程中看出,必須引入大根堆、雙向鍊錶。

貪心是當前最優,導致最終全域性最優。例子中種第1、2、3棵樹,很像dp中的階段。

ac**:

#include#include#include#define ll long long

using namespace std;

const int maxn=5e5+5;

int n,m,l[maxn],r[maxn];

ll a[maxn],ans;

bool ***[maxn];

struct node;

node t;

bool operator < (const node &a,const node &b)

while(m--)

printf("%lld",ans);

return 0;

}

洛谷P1484種樹(堆 較難貪心)

題意很清晰很好懂,做起來就難了。資料範圍小的化可搜尋可dp,but資料這麼大是不可能的了,較難貪心 a i 或左加右只選乙個最大的 堆 每次取出最大的 1 include 2 include 3 include 4 using namespace std 5 typedef long long ll...

洛谷 P1484 種樹

本題說每選乙個坑,它的左右兩個坑都不能選了,可是我們沒有辦法確定我們選某個坑一定是最優解,怎麼辦呢?我們設定乙個反悔機制,每當選乙個坑,就新設定乙個點,使這個點的值為這個坑兩邊的和減去當前坑的差.為什麼這樣做是對的呢?感性想一下,如果再後面的選坑過程中,我們選到了這個新設定的點,說明我們選上文的那個...

洛谷 P1484 種樹 思維 堆

洛谷 p1484 種樹 思維 堆 很容易想到用乙個大根堆來儲存每個位置的獲利,但我們不能每次都取出根元素後,將其兩邊的元素標記位不可選擇,因為這個根元素兩邊的元素之和很可能大於這個根元素,這時我們選擇的就不是根元素,而是兩邊的元素,所以我們要有乙個反悔選擇的機會,我們在選擇根元素的時候,在總獲利中加...