您的位置:首页 > 其它

51nod1053 最大M子段和 V2

2018-06-11 13:35 148 查看

$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

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: