$n leq 50000$的序列,问选不超过$m leq 50000$个区间使得和最大。
如果正数区间总数比$m$小那肯定全选。否则有两种方式减少区间数量:丢掉一个正区间;补一个负区间连接两个正区间。贪心即可。
先把左右端的负数去掉,然后把正区间和负区间处理出来。优先队列维护区间值,然后开个链表模拟合并(删左右,改自己)。注意删右边时调整右端点。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<set> 7 #include<queue> 8 //#include<vector> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 #define LL long long 14 int qread() 15 { 16 char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1); 17 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f; 18 } 19 20 //Pay attention to '-' , LL and double of qread!!!! 21 22 int n,m; 23 #define maxn 50011 24 #define LL long long 25 26 LL Abs(LL x) {return x>0?x:-x;} 27 28 int a[maxn]; LL sum[maxn]; 29 int b[maxn],lb,ll[maxn],rr[maxn]; bool vis[maxn]; 30 struct qnode 31 { 32 LL v; int id; 33 bool operator > (const qnode &b) const {return v>b.v;} 34 }; 35 priority_queue<qnode,vector<qnode>,greater<qnode> > q; 36 int main() 37 { 38 n=qread(); m=qread(); 39 for (int i=1;i<=n;i++) a[i]=qread(); 40 { 41 int L=1,R=n; while (a[L]<=0) L++; while (a[R]<=0) R--; 42 for (int i=L,j=1;i<=R;i++,j++) a[j]=a[i]; 43 n=R-L+1; a[n+1]=0; 44 } 45 for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; 46 47 LL ans=0; 48 int cnt=0; 49 { 50 LL tmp=a[1],last=1; 51 for (int i=2;i<=n+1;i++) 52 { 53 if (tmp>0 && a[i]<=0) 54 { 55 b[++lb]=last; 56 q.push((qnode){tmp,lb}); 57 ans+=tmp; cnt++; tmp=a[i]; last=i; 58 } 59 else if (tmp>0 && a[i]>0) tmp+=a[i]; 60 else if (tmp<=0 && a[i]>0) 61 { 62 b[++lb]=last; 63 q.push((qnode){-tmp,lb}); 64 tmp=a[i]; last=i; 65 } 66 else tmp+=a[i]; 67 } 68 } 69 70 for (int i=0;i<=lb+1;i++) ll[i]=i-1,rr[i]=i+1; b[lb+1]=n+1; 71 if (cnt<=m) {printf("%lld ",ans); return 0;} 72 while (m<cnt--) 73 { 74 while (vis[q.top().id]) q.pop(); 75 ans-=q.top().v; int now=q.top().id; q.pop(); 76 77 if (ll[now]==0) 78 { 79 vis[rr[now]]=1; 80 vis[now]=1; 81 int u=rr[now]; ll[rr[now]]=ll[now]; rr[ll[now]]=rr[now]; 82 ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u]; 83 } 84 else if (rr[now]==lb+1) 85 { 86 vis[ll[now]]=1; 87 vis[now]=1; 88 int u=ll[now]; ll[rr[now]]=ll[now]; rr[ll[now]]=rr[now]; 89 ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u]; b[lb+1]=b[u]; 90 } 91 else 92 { 93 int L=b[ll[now]],R=b[rr[rr[now]]]-1; 94 vis[ll[now]]=1; vis[rr[now]]=1; int u=ll[now],v=rr[now]; 95 b[now]=L; q.push((qnode){Abs(sum[R]-sum[L-1]),now}); 96 ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u]; 97 ll[rr[v]]=ll[v]; rr[ll[v]]=rr[v]; 98 } 99 } 100 101 printf("%lld ",ans); 102 return 0; 103 }