BZOJ 2288 生日禮物

2022-05-05 02:21:12 字數 1575 閱讀 6369

【題目鏈結】

【演算法】

先將這個序列的正負數合併起來,變成乙個正負交替的序列

如果新序列的正數個數小於等於m,那麼直接輸出正數的和即可

否則,我們可以將某些正數和負數合併起來,或者不要某些正數

將所有數按絕對值排序,放入堆中,問題就轉化為了 : 在這些數中選出(cnt - m)個數(其中cnt為正數的個數),

選了乙個數後相鄰的兩個數就不能選,使得最後的和盡可能小 

這個問題可以用ctsc2007資料備份的方法來解決,詳見 : 

【**】

#includeusing

namespace

std;

const

int maxn = 1e5 + 10

;const

int inf =2e9;

struct

info

;int

i,n,m,l,r,cnt,ans,len;

inta[maxn],b[maxn],val[maxn],pre[maxn],nxt[maxn];

bool

visited[maxn];

info tmp;

class

heap

inline

void up(int

x)

}inline

void down(int

x)

}inline

void

insert(info x)

inline

void

del()

inline info

get()

} h;

intmain()

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

for (i = 1; i <= len; i++)

else b[i] = -b[i];

}if (cnt <=m)

for (i = 1; i <= len; i++));}

b[0] = b[len+1] =inf;

for (i = m; i < cnt; i++)

ans -=tmp.d;

h.del();

visited[pre[tmp.pos]] = true

; visited[nxt[tmp.pos]] = true

; b[tmp.pos] = b[pre[tmp.pos]] + b[nxt[tmp.pos]] -tmp.d;

nxt[pre[pre[tmp.pos]]] =tmp.pos;

pre[tmp.pos] =pre[pre[tmp.pos]];

pre[nxt[nxt[tmp.pos]]] =tmp.pos;

nxt[tmp.pos] =nxt[nxt[tmp.pos]];

h.insert((info));

}

printf(

"%d\n

",ans);

return0;

}

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

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

BZOJ2288 生日禮物 堆 鍊錶 貪心

顯然符號相同的一段會一起被選,因此先合併符號相同的各段,最終得到正數負數相間的序列。設此時有 cnt cntcn t 個正數,且其和為 sum sumsu m,若 cnt m cnt leq m cnt m,則答案為 sum sumsu m。否則,每次找出絕對值最小的數,將其與序列中相鄰兩數合併,直...

BZOJ 1293 生日禮物

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