1. 程式人生 > >【BZOJ 2288】 生日禮物

【BZOJ 2288】 生日禮物

禮物 col line .html 正負交替 ace vat scan ins

【題目鏈接】

https://www.lydsy.com/JudgeOnline/problem.php?id=2288

【算法】

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

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

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

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

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

這個問題可以用CTSC2007數據備份的方法來解決,詳見 : https://www.cnblogs.com/evenbao/p/9252503.html

【代碼】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
const int INF = 2e9;

struct info
{
        int d,pos;
};

int i,n,m,l,r,cnt,ans,len;
int a[MAXN],b[MAXN],val[MAXN],pre[MAXN],nxt[MAXN];
bool visited[MAXN]; info tmp; class Heap { private : int tot; info hp[MAXN]; public : inline bool cmp(info a,info b) { return a.d < b.d; } inline
void Up(int x) { if (x == 1) return; int fa = x >> 1; if (cmp(hp[x],hp[fa])) { swap(hp[x],hp[fa]); Up(fa); } } inline void Down(int x) { int son = x << 1; if (son > tot) return; if ((son + 1 <= tot) && cmp(hp[son+1],hp[son])) son++; if (cmp(hp[son],hp[x])) { swap(hp[son],hp[x]); Down(son); } } inline void insert(info x) { tot++; hp[tot] = x; Up(tot); } inline void del() { swap(hp[1],hp[tot]); tot--; Down(1); } inline info get() { return hp[1]; } } H; int main() { scanf("%d%d",&n,&m); for (i = 1; i <= n; i++) scanf("%d",&a[i]); while (n && a[n] <= 0) n--; i = 1; while (i <= n && a[i] <= 0) i++; if (i > n) { printf("%d\n",0); return 0; } for (; i <= n; i++) { if ((a[i] > 0 && a[i-1] > 0) || (a[i] <= 0 && a[i-1] <= 0)) b[len] += a[i]; else b[++len] = a[i]; } for (i = 1; i <= len; i++) { if (b[i] > 0) { ans += b[i]; cnt++; } else b[i] = -b[i]; } if (cnt <= m) { printf("%d\n",ans); return 0; } for (i = 1; i <= len; i++) { pre[i] = i - 1; nxt[i] = i + 1; H.insert((info){b[i],i}); } b[0] = b[len+1] = INF; for (i = m; i < cnt; i++) { tmp = H.get(); while (visited[tmp.pos]) { H.del(); tmp = H.get(); } 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){b[tmp.pos],tmp.pos}); } printf("%d\n",ans); return 0; }

【BZOJ 2288】 生日禮物