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. spring较为常用注解

    @Configuration 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被Annotat ...

  2. [转帖]从0开始的高并发(一)--- Zookeeper的基础概念

    从0开始的高并发(一)--- Zookeeper的基础概念 https://juejin.im/post/5d0bd358e51d45105e0212db 前言 前面几篇以spring作为主题也是有些 ...

  3. 列表,元组以及range

    列表,元组以及range 一.列表(list) 列表是数据类型之一,它有序,可变,支持索引 作用:存储数据,支持的数据类型很多:字符串,数字,布尔值,列表等 # 定义一个列表 lst = ['alex ...

  4. 国内P2P网贷行业再次大清理,仅剩646家

    最近有网贷行业头部网站流出消息,国内网贷行业再次迎来大洗牌 清扫之后网贷的平台数量仅剩646家,数量陡降 根据小编了解.自2007年国外网络借贷平台模式引入中国以来,由于国家一时没有做出相应规定个条例 ...

  5. Fiddler的使用总结

    关于Fiddler的使用过程中的总结: 1. 配置手机抓包的过程,以后再补充 2.使用Fiddler发送请求 1) 第一步 抓取接口,获取请求方式,以及请求参数  2) 第二步 请求接口 点击Exec ...

  6. redis - redis安装与启动

    redis安装 下载redis安装包 wget http://download.redis.io/releases/redis-5.0.7.tar.gz 解压缩 tar -xzf redis-5.0. ...

  7. SpringBoot整合freemarker 引用基础

    原 ElasticSearch学习笔记Ⅲ - SpringBoot整合ES 新建一个SpringBoot项目.添加es的maven坐标如下: <dependency> <groupI ...

  8. c# 基于WebApi的快速开发框架FastFramework

    一.框架简介 此框架是针对于webapi进行开发,项目分层是基于ABP框架的分层,更好的抽离业务逻辑关系,ABP是基于EF做数据访问层,本人个人比较喜欢Dapper,就把数据访问层封装成了Dapper ...

  9. C++STL—map的使用

    最近写的一道题用到了STL中的map,这部分内容之前没有系统学过,这里就简单归纳一下吧. 资料来源: https://www.w3cschool.cn/cpp/cpp-fu8l2ppt.html ht ...

  10. 非洲affrike单词

    affrike 英文单词,含义是非洲,非洲大陆. 中文名:非洲 外文名:affrike 目录 释义 affrike noun名词 非洲,也用做africa 1.Word Origin and Hist ...