51nod1053 最大M子段和 V2

$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\n",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\n",ans);
102     return 0;
103 }
View Code

 

posted @ 2018-06-11 13:35  Blue233333  阅读(238)  评论(0编辑  收藏  举报