【BZOJ3502/2288】PA2012 Tanie linie/【POJ Challenge】生日禮物 堆+鏈表(模擬費用流)
阿新 • • 發佈:2017-09-20
line make 前驅 string urn return namespace 禮物 iostream
7 -3 4 -9 5
【BZOJ3502】PA2012 Tanie linie
Description
n個數字,求不相交的總和最大的最多k個連續子序列。
1<= k<= N<= 1000000。
Sample Input
5 27 -3 4 -9 5
Sample Output
13題解:跟1150和2151差不多。
我們先做一些預處理,因為連續的正數和連續的負數一定是要麽都選要麽都不選,所以可以將它們合並成一個數,同時區間中的零以及左右兩端的負數沒有意義,可以將它們刪掉。然後我們得到的序列就變成:正-負-正-...-負-正。
然後我們貪心的把所有正數都選了,如果正數的部分<=k,那麽直接取光即可,否則,我們還要將我們的子串個數減少一些。如何減少呢?1:將某個正數由選變為不選。2.將某個負數由不選變為選。我們發現,這兩種情況都會使答案減少:那個數的絕對值,所以我們可以用堆維護所有數的絕對值,然後每次都貪心的選取絕對值小的。
但是直接貪心肯定不行,我們要模擬費用流的過程,也就是加入一個反悔操作。發現:如果對一個整數進行了1操作,那麽我們就無法對它相鄰的負數進行2操作;如果對一個負數進行了2操作,那麽我們就無法對它相鄰的正數進行1操作。所以我們再堆中刪掉與它相鄰的點。那麽怎麽反悔呢?如果當前是b,b的前驅是a,後繼是c,那麽向堆中加入a+c-b。如果再次選擇了a+c-b,意味著我們撤銷了對b的操作,而是對a和c進行操作,這樣就和費用流是一樣的了。
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <utility> #include <algorithm> #define mp(A,B) make_pair(A,B) using namespace std; typedef long long ll; const int maxn=1000010; int n,m,k; ll ans; ll v[maxn],p[maxn]; int pre[maxn],nxt[maxn],del[maxn]; typedef pair<ll,int> pli; priority_queue<pli> q; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); int i,a,b,tp=0; for(i=1;i<=n;i++) { v[i]=rd(); if(v[i]>0) { ans+=v[i]; if(p[tp]>0) p[tp]+=v[i]; else p[++tp]=v[i]; } if(v[i]<0) { if(p[tp]<=0) p[tp]+=v[i]; else p[++tp]=v[i]; } } if(p[tp]<=0) tp--; n=tp; if((n+1)>>1<=m) { printf("%lld\n",ans); return 0; } m=((n+1)>>1)-m; for(i=1;i<=n;i++) p[i]=abs(p[i]),q.push(mp(-p[i],i)),pre[i]=i-1,nxt[i]=(i<n)?(i+1):0; while(m--) { while(del[q.top().second]) q.pop(); ans+=q.top().first,i=q.top().second,q.pop(); a=pre[i],b=nxt[i],del[a]=del[b]=1; if(a&&b) { pre[i]=pre[a],nxt[i]=nxt[b]; if(pre[i]) nxt[pre[i]]=i; if(nxt[i]) pre[nxt[i]]=i; p[i]=p[a]+p[b]-p[i],q.push(mp(-p[i],i)); } else { pre[i]=pre[a],nxt[i]=nxt[b]; if(pre[i]) nxt[pre[i]]=nxt[i]; if(nxt[i]) pre[nxt[i]]=pre[i]; del[i]=1; } } printf("%lld",ans); return 0; }
【BZOJ3502/2288】PA2012 Tanie linie/【POJ Challenge】生日禮物 堆+鏈表(模擬費用流)