BZOJ2288 生日禮物 堆 鍊錶 貪心

2021-10-01 02:12:11 字數 1702 閱讀 3588

顯然符號相同的一段會一起被選,因此先合併符號相同的各段,最終得到正數負數相間的序列。

設此時有 cnt

cntcn

t 個正數,且其和為 sum

sumsu

m,若 cnt

≤m

cnt \leq m

cnt≤

m,則答案為 sum

sumsu

m。否則,每次找出絕對值最小的數,將其與序列中相鄰兩數合併,直至 cnt

=m

cnt = m

cnt=m。

若找出的數是負數,則相當於以最小的代價將兩段正數連線;

若找出的數是正數,則相當於捨棄該正數,以消除負數的影響。

每次操作均會使 cnt

=cnt

−1

cnt = cnt - 1

cnt=cn

t−1,sum

=sum

−∣a[

i]

∣sum = sum - |a[i]|

sum=su

m−∣a

[i]∣

,a [i

]a[i]

a[i]

為選出的值。

這也可以解釋為什麼每次取出絕對值最小的數。

可以用堆和鍊錶來實現,若取出的是負數且處於鍊錶邊界,則直接捨棄即可。

#include

#include

#include

#include

using

namespace std;

inline

intread()

while

(c >=

'0'&& c <=

'9')

num = num *

10+ c -

'0', c =

getchar()

;return flag * num;

}const

int maxn =

1e5+5;

struct node1 };

struct node2 list[maxn]

;struct heap

voidup(

int p)

else

break;}

}void

down

(int p)

else

break;}

}void

push

(node1 x)

void

pop(

int p =1)

} heap;

inline

void

del(

int x)

int a[maxn]

, tot;

intmain()

for(

int i =

1; i <= tot;

++i)

if(cnt <= m)

while

(cnt > m)

else

if(y.r == tot +1)

else

x.v = y.v;

heap.

push

(x);

}printf

("%d"

, sum)

;return0;

}

bzoj2288 生日禮物(貪心)(堆)(鍊錶)

ftiasch 18歲生日的時候,lqp18 31給她看了乙個神奇的序列 a1,a2,an.她被允許選擇不超過 m 個連續的部分作為自己的生日禮物。自然地,ftiasch想要知道選擇元素之和的最大值。你能幫助她嗎?相鄰的兩個數如果同為正數或負數可以合併成乙個大的正數或負數,這樣整個數列就成了正負交替...

BZOJ 2288 生日禮物

題目鏈結 演算法 先將這個序列的正負數合併起來,變成乙個正負交替的序列 如果新序列的正數個數小於等於m,那麼直接輸出正數的和即可 否則,我們可以將某些正數和負數合併起來,或者不要某些正數 將所有數按絕對值排序,放入堆中,問題就轉化為了 在這些數中選出 cnt m 個數 其中cnt為正數的個數 選了乙...

BZOJ 1293 生日禮物

我發現bzoj的水題都比較高檔昂。這道題的基本思想是,每次用優先佇列把位置最靠前的顏色彈出來,並把與它顏色相同的下乙個點的位置進佇列,每次更新最優長度。1.初始化 每個點的下乙個相同顏色點的位置。2.將每個顏色的第乙個點入佇列,算第乙個狀態。3.每次將佇列最前端的顏色彈出,將他的下乙個點放入佇列,更...