n个数字,求不相交的总和最大的最多k个连续子序列。
1<= k<= N<= 1000000。
n个数字,求不相交的总和最大的最多k个连续子序列。
1<= k<= N<= 1000000。
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define pr pair<ll,int> using namespace std; ll s[1000010]; int pre[1000010]; int suf[1000010]; int vis[1000010]; int tot; int n,k; ll ans,x; priority_queue< pr,vector<pr>,greater<pr> >q; int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%lld",&x); if(x>0) { ans+=x; if(s[tot]>0) { s[tot]+=x; } else { s[++tot]=x; } } if(x<0) { if(s[tot]<=0) { s[tot]+=x; } else { s[++tot]=x; } } } if(s[tot]<=0) { tot--; } n=tot; if((n+1)/2<=k) { printf("%lld",ans); return 0; } k=(n+1)/2-k; for(int i=1;i<=n;i++) { pre[i]=i-1; suf[i]=i+1; s[i]=abs(s[i]); q.push(make_pair(s[i],i)); } suf[n]=0; while(k--) { while(vis[q.top().second])q.pop(); ans-=q.top().first; int now=q.top().second; q.pop(); vis[pre[now]]=vis[suf[now]]=1; if(pre[now]&&suf[now]) { s[now]=s[pre[now]]+s[suf[now]]-s[now]; q.push(make_pair(s[now],now)); pre[now]=pre[pre[now]]; suf[now]=suf[suf[now]]; if(pre[now]) { suf[pre[now]]=now; } if(suf[now]) { pre[suf[now]]=now; } } else { vis[now]=1; pre[now]=pre[pre[now]]; suf[now]=suf[suf[now]]; if(pre[now]) { suf[pre[now]]=suf[now]; } if(suf[now]) { pre[suf[now]]=pre[now]; } } } printf("%lld",ans); }
BZOJ3502PA2012Tanie linie&BZOJ2288[POJ Challenge]生日礼物——模拟费用流+链表+堆
原文:https://www.cnblogs.com/Khada-Jhin/p/10429517.html