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

收起

 

输入

第1行:2个数N和M,中间用空格分隔。N为整数的个数,M为划分为多少段。(2 <= N , M <= 50000)
第2 - N+1行:N个整数(-10^9 <= a[i] <= 10^9)

输出

输出这个最大和

输入样例

7 2
-2
11
-4
13
-5
6
-2

输出样例

26

v2果然是难了,还用dp就超时了,学无止境,本道题采用特别巧妙的贪心思想的方法,把相邻的正数或者负数,都加到一起,形成新的序列,也就是正数和负数交叉的序列,假如原序列是1 2 -3 -4 3,压缩后:
3 -7 3,存到一个新的数组里,我们用ans记录所有正数的和,显然新数组里每一项都是一段,我们还要记录所有正数段得到个数,我们要保持正数段的个数在m之内,所以我们把所有的数段的绝对值,以及位置,存到一个set里,
也可以用链表,这样做的目的是用负数填补空缺,从而把两个正数段合并为一段,我们需要知道每一段左右分别是谁,方便合并,不是单纯的下表加1和减1,因为合并多了,中间会有很多无效的位置,当然了用链表就不需要考虑这些问题,直接删除节点即可。
那么怎么来合并呢,set里存绝对值和位置组成的pair,这样排序就按照绝对值排序了,每次选择绝对值最小的,假如这个数是正的,那么就用ans减去,然后跟两边的合并,因为set里所有的负数绝对值都比他大,所以ans肯定不包括它了,如果是负数,也是ans减去绝对值,负数跟两边的整数合并了,实际上让ans减少了。
代码:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <set>
using namespace std;
typedef long long ll;
int n,m;
ll d,last;
ll s[];
int l[],r[];
int sc;
void modify(int cur) {///修改左右相邻结点的下标
int ll = l[cur],rr = r[cur];
if(ll) {
r[ll] = rr;
}
if(rr) {
l[rr] = ll;
}
}
int main() {
while(~scanf("%d%d",&n,&m)) {
ll sum = ,ans = ,c = ;
set<pair<ll,int> > ss;
for(int i = ;i < n;i ++) {
scanf("%lld",&d);
if(d * last < ) {
s[++ sc] = sum;
if(sc == && sum < ) sc --;
sum = d;
}
else sum += d;
last = d;
}
if(sum > ) s[++ sc] = sum;
c = (sc + ) / ;
for(int i = ;i <= sc;i ++) {
ss.insert(make_pair(abs(s[i]),i));
ans += (s[i] > ? s[i] : );
l[i] = i - ;
r[i] = i + ;
}
r[sc] = ;
while(c > m) {
int cur = ss.begin() -> second;
ss.erase(ss.begin());
if(s[cur] < && (!l[cur] || !r[cur])) continue;///如果是负数,而且是处在首尾的位置那么就没必要合并了。
ans -= abs(s[cur]);
s[cur] += s[l[cur]] + s[r[cur]];
if(l[cur]) {
ss.erase(make_pair(abs(s[l[cur]]),l[cur]));
modify(l[cur]);
}
if(r[cur]) {
ss.erase(make_pair(abs(s[r[cur]]),r[cur]));
modify(r[cur]);
}
if(s[cur]) ss.insert(make_pair(abs(s[cur]),cur));
c --;
}
printf("%lld\n",ans);
}
return ;
}

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

  1. 51nod 1065 最小正子段和

    题目链接:51nod 1065 最小正子段和 房教说用前缀和做,然后看了别人博客懂了后就感觉,这个真有意思... #include<cstdio> #include<cstring& ...

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

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

  3. 51nod 1254 最大子段和 V2

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

  4. 51nod 循环数组最大子段和

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 对于普通的数组,只要求一次最大子段和即可.但是这题是可以循环的,所 ...

  5. 51nod 1049 1049 最大子段和 (dp)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1049 令 dp[i]表示为以a[i]结尾的最大子段和,则  dp[i]= ...

  6. 51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084 1084 矩阵取数问题 V2  基准时间限制:2 秒 空 ...

  7. 51nod 1115 最大M子段和 V3

    环形最大M子段和,N个整数组成的序列排成一个环,a[1],a[2],a[3],…,a[n](a[n-1], a[n], a[1]也可以算作1段),将这N个数划分为互不相交的M个子段,并且这M个子段的和 ...

  8. 最大M子段和 V2

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

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

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

随机推荐

  1. 简单使用Moq框架

    Moq框架简单使用   系列目录 Moq库简介及安装 Moq简介 Moq是.net平台下的一个非常流行的模拟库,只要有一个接口它就可以动态生成一个对象,底层使用的是Castle的动态代理功能. 它的流 ...

  2. DevOps-ISC,CSS,Prometheus,Ansible ,Terraform,zabbix

    https://www.terraform.io/ Terraform Use Infrastructure as Code to provision and manage any cloud, in ...

  3. (CSDN 迁移) jFinal找不到或无法加载主类

    错误: 找不到或无法加载主类 com.demo.common.DemoConfig 项目上右键 -> Build Path -> Order and Export 修改顺序: 从上到下依次 ...

  4. (CSDN迁移)JAVA多线程实现-继承Thread

    继承Thread方法: extends Thread 重写覆盖run()方法: @Override public void run() 通过start()方法启动线程. threadDemo01.st ...

  5. time 库

    time 库的三类函数 时间获取: >>> import time >>> time.time() 1570150181.4052463#单位为秒 >> ...

  6. 【转帖】Spark设计理念与基本架构

    Spark设计理念与基本架构 https://www.cnblogs.com/swordfall/p/9280006.html 1.基本概念 Spark中的一些概念: RDD(resillient d ...

  7. IntelliJ IDEA 删除自定义的 Maven 框架依赖

    IntelliJ IDEA 删除自定义的 Maven 框架依赖 IntelliJ Idea中添加Maven Archetype,但是IntelliJ Idea中并没有提供删除的方法. windows中 ...

  8. Spark学习(1) Spark入门

    什么事spark Spark是一种快速.通用.可扩展的大数据计算引擎.项目是用Scala进行编写,基于内存计算的 包括交互式查询和流处理 spark内置项目 Spark SQL:是 Spark 用来操 ...

  9. leetcode的Hot100系列--347. 前 K 个高频元素--hash表+直接选择排序

    这个看着应该是使用堆排序,但我图了一个简单,所以就简单hash表加选择排序来做了. 使用结构体: typedef struct node { struct node *pNext; int value ...

  10. 解决docker容器中Centos7系统的中文乱码

    解决docker容器中Centos7系统的中文乱码问题有如下两种方案: 第一种只能临时解决中文乱码: 在命令行中执行如下命令: # localedef -i zh_CN -f UTF-8 zh_CN. ...