$n \leq 50000$的序列,问选不超过$m \leq 50000$个区间使得和最大。

如果正数区间总数比$m$小那肯定全选。否则有两种方式减少区间数量:丢掉一个正区间;补一个负区间连接两个正区间。贪心即可。

先把左右端的负数去掉,然后把正区间和负区间处理出来。优先队列维护区间值,然后开个链表模拟合并(删左右,改自己)。注意删右边时调整右端点。

 //#include<iostream>
#include<cstring>
#include<cstdio>
//#include<time.h>
//#include<complex>
//#include<set>
#include<queue>
//#include<vector>
#include<algorithm>
#include<stdlib.h>
using namespace std; #define LL long long
int qread()
{
char c; int s=,f=; while ((c=getchar())<'' || c>'') (c=='-') && (f=-);
do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s*f;
} //Pay attention to '-' , LL and double of qread!!!! int n,m;
#define maxn 50011
#define LL long long LL Abs(LL x) {return x>?x:-x;} int a[maxn]; LL sum[maxn];
int b[maxn],lb,ll[maxn],rr[maxn]; bool vis[maxn];
struct qnode
{
LL v; int id;
bool operator > (const qnode &b) const {return v>b.v;}
};
priority_queue<qnode,vector<qnode>,greater<qnode> > q;
int main()
{
n=qread(); m=qread();
for (int i=;i<=n;i++) a[i]=qread();
{
int L=,R=n; while (a[L]<=) L++; while (a[R]<=) R--;
for (int i=L,j=;i<=R;i++,j++) a[j]=a[i];
n=R-L+; a[n+]=;
}
for (int i=;i<=n;i++) sum[i]=sum[i-]+a[i]; LL ans=;
int cnt=;
{
LL tmp=a[],last=;
for (int i=;i<=n+;i++)
{
if (tmp> && a[i]<=)
{
b[++lb]=last;
q.push((qnode){tmp,lb});
ans+=tmp; cnt++; tmp=a[i]; last=i;
}
else if (tmp> && a[i]>) tmp+=a[i];
else if (tmp<= && a[i]>)
{
b[++lb]=last;
q.push((qnode){-tmp,lb});
tmp=a[i]; last=i;
}
else tmp+=a[i];
}
} for (int i=;i<=lb+;i++) ll[i]=i-,rr[i]=i+; b[lb+]=n+;
if (cnt<=m) {printf("%lld\n",ans); return ;}
while (m<cnt--)
{
while (vis[q.top().id]) q.pop();
ans-=q.top().v; int now=q.top().id; q.pop(); if (ll[now]==)
{
vis[rr[now]]=;
vis[now]=;
int u=rr[now]; ll[rr[now]]=ll[now]; rr[ll[now]]=rr[now];
ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u];
}
else if (rr[now]==lb+)
{
vis[ll[now]]=;
vis[now]=;
int u=ll[now]; ll[rr[now]]=ll[now]; rr[ll[now]]=rr[now];
ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u]; b[lb+]=b[u];
}
else
{
int L=b[ll[now]],R=b[rr[rr[now]]]-;
vis[ll[now]]=; vis[rr[now]]=; int u=ll[now],v=rr[now];
b[now]=L; q.push((qnode){Abs(sum[R]-sum[L-]),now});
ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u];
ll[rr[v]]=ll[v]; rr[ll[v]]=rr[v];
}
} printf("%lld\n",ans);
return ;
}

51nod1053 最大M子段和 V2的更多相关文章

  1. 51Nod1053 最大M子段和V2 二分+DP

    传送门 直接DP的话最多也只能做到\(O(nm)\),对于\(5\times 10^4\)的数据范围实在无能为力 夹克老爷提供的做法是贪心,思想大概是在调整的同时,合理构造每个选择对应的新状态,使得新 ...

  2. 最大M子段和 V2

    51nod1053 这题还是我们熟悉的M子段和,只不过N,M<=50000. 这题似乎是一个堆+链表的题目啊 开始考虑把所有正数负数锁在一起. 比如: 1 2 3 -1 –2 -3 666 缩成 ...

  3. 51nod 1053 最大M子段和 V2

    N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的.如果M >= N个数中正数的个数,那么输出所有正数的和. 例如:-2 ...

  4. [51nod1254]最大子段和 V2

    N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  5. 51nod 1254 最大子段和 V2 ——单调栈

    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  6. 51nod 1254 最大子段和 V2

    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  7. 51nod1524 最大子段和V2

    题干 N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数 ...

  8. 51nod1254 最大子段和 V2 DP

    ---题面--- 题解: 表示今天做题一点都不顺.... 这题也是看了题解思路然后自己想转移的. 看的题解其实不是这道题,但是是这道题的加强版,因为那道题允许交换k对数. 因为我们选出的是连续的一段, ...

  9. 51Nod 最大M子段和系列 V1 V2 V3

    前言 \(HE\)沾\(BJ\)的光成功滚回家里了...这堆最大子段和的题抠了半天,然而各位\(dalao\)们都已经去做概率了...先%为敬. 引流之主:老姚的博客 最大M子段和 V1 思路 最简单 ...

随机推荐

  1. 如何计算CDS view里两个时间戳之间的天数间隔

    ABAP透明表里的时间戳,数据类型为dec: 有个需求:计算这两个时间戳之间的天数间隔,丢弃时间戳年-月-日8位后面的小时:分钟:秒. 举个例子:如果时间戳是20180918173132,丢弃1731 ...

  2. Luogu P5352 Terrible Homework

    神仙@TheLostWeak出的题,因为他最近没时间所以我先写一下sol(其实我也没什么时间) 作为一道简单的数据结构题想必大家都能看出必须用LCT维护信息吧 一个朴素的想法就是直接维护四种操作的值, ...

  3. (四)VMware Harbor 配置文件

    VMware Harbor 配置文件 :harbor.yml # Configuration file of Harbor # The IP address or hostname to access ...

  4. Schur 三角化定理的推论

    将学习到什么 从 Schur 的酉三角化定理可以收获一批结果,在这一部分介绍重要的几个.   迹与行列式 相似矩阵具有相同的特征多项式, 从特征多项式一节中, 我们又知道,相似矩阵的迹以及行列式都是相 ...

  5. noj-1102-黑白图像

    1 //题目地址:http://acm.njupt.edu.cn/acmhome/problemdetail.do?method=showdetail&id=1102              ...

  6. vs code背景图片的设置

    使用vs code编辑器的时候,每次看到黑色的背景,会感觉到很大的视觉疲劳,今天来换换背景来看下效果 你需要安装的插件是background 然后在文件 => 首选项 => 设置搜索bac ...

  7. BZOJ4513 SDOI2016 储能表 记忆化搜索(动态规划)

    题意: 题面中文,不予翻译:SDOI2016储能表 分析: 据说有大爷用一些奇怪的方法切掉了这道题%%%%% 这里用的是大众方法——动态规划. 其实这是一道类似于二进制数位dp的动态规划题,(但是实际 ...

  8. perl5中锚位修饰符\A \z \Z 和perl4中^(开头)和$(结尾)的区别

    习惯使用perl4的开发者总是用^表示字符串开头锚位,用$表示字符串结尾锚位,比如\^https://\ 将会匹配所有以https://开头的字符串,同样,\.bmp$\将会匹配所有以.bmp结尾的字 ...

  9. docker:安装mysql多个

    文章来源:https://www.cnblogs.com/hello-tl/p/9238298.html 1.首先安装docker 参照一下网址安装docker docker:安装 https://w ...

  10. 《嵌入式linux应用程序开发标准教程》笔记——6.文件IO编程

    前段时间看APUE,确实比较详细,不过过于详细了,当成工具书倒是比较合适,还是读一读这种培训机构的书籍,进度会比较快,遇到问题时再回去翻翻APUE,这样的效率可能更高一些. <嵌入式linux应 ...