51nod 最大M子段和系列(1052、1053、1115)
51nod1052
数据量小,可使用O(N*M)的DPAC,递推公式:
dp[i][j]=max(dp[i-1][j-1], dp[i][j-1])+a[j];
dp[i][j]表示前j个数取 i 段的最大子段和,用滚动数组思想优化空间。
51nod1053、51nod1115
进阶版并不使用dp,容易被第一题的思维误导钻到死胡同里。
- 可以先做一下处理以便思考,将原序列连续的正数和连续的负数合并,即可得到一个正负交替的序列;
- 设新的序列中有k个正数,若m>=k则输出所有正数的和;
- 接着考虑m<k的情况,首先所有正数的和(设为S)是我们的初始状态,但因m<k,故我们需要放弃一些正数,或者合并两个相邻的正数(两正数之间的复数也要合并,则相当于额外要一个负数);
- 显然我们肯定要放弃那些绝对值更小的正数或附加绝对值更小的负数,这显然是一个贪心问题了;
- 既然是以绝对值为标准选数,不妨将所有负数变成正数,然后选出k-m个最小的数来,然后S减去他们就是结果;
- 以上可以通过维护一个堆(优先队列)来达到目的,但要处理几个问题;
- 每选出一个数,需要将它与其相邻的两个数合并后重新加入堆,而原数要重堆中删除是个麻烦的事情;
- 这里可以通过额外的标记处理,所以还需要维护每个数实时的“左邻右舍”,V2需要处理一下边界问题,V3则更简单些;
- 代码如下:
#include<iostream>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
const LL maxn = 1e5+5, INF = 1e9;
int a[maxn], l[maxn], r[maxn];
bool vis[maxn];
LL s[maxn];
priority_queue< pair<LL, int> > q;
int main()
{
//freopen("stdin","r",stdin); int n, m, t;
cin>>n>>m;
int cnt=1;
LL sum=0;
cin>>s[1];
for(int i=2; i<=n; ++i)
{
cin>>t;
if((t>=0) != (s[cnt]>=0)) s[++cnt]=t;
else s[cnt]+=t;
}
//cout<<s[0]<<endl<<s[cnt]<<endl<<endl;
while(s[cnt]*s[1]>=0) s[1]+=s[cnt--];
t=0;
for(int i=1; i<=cnt; ++i)
{
//cout<<s[i]<<endl;
vis[i]=false;
l[i]=i-1;
r[i]=i+1;
if(s[i]>0)
{
sum+=s[i];
s[i]=-s[i];
t++;
}
q.push( make_pair(s[i],i));
}
l[1]=cnt;
r[cnt]=1;
cnt=t;
if(m>=cnt)
{
cout<<sum<<endl;
return 0;
}
while(!q.empty() && cnt>m)
{
pair<LL, int> tmp=q.top();
q.pop();
if(vis[tmp.second])
{
continue;
}
else
{
cnt--;
sum+=s[tmp.second];
s[tmp.second]=s[l[tmp.second]]+s[r[tmp.second]]-s[tmp.second];
q.push( make_pair(s[tmp.second], tmp.second));
vis[l[tmp.second]]=true;
vis[r[tmp.second]]=true;
r[l[l[tmp.second]]]=tmp.second;
l[r[r[tmp.second]]]=tmp.second;
l[tmp.second]=l[l[tmp.second]];
r[tmp.second]=r[r[tmp.second]];
}
}
cout<<max(0ll,sum)<<endl;
return 0;
}
51nod 最大M子段和系列(1052、1053、1115)的更多相关文章
- 51nod 最大M子段和系列
1052 最大M子段和 N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的.如果M >= N个数中正数的个数,那么输出所 ...
- 51Nod 最大M子段和系列 V1 V2 V3
前言 \(HE\)沾\(BJ\)的光成功滚回家里了...这堆最大子段和的题抠了半天,然而各位\(dalao\)们都已经去做概率了...先%为敬. 引流之主:老姚的博客 最大M子段和 V1 思路 最简单 ...
- 51Nod 1049 最大子段和
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1049 #include<iostream> #i ...
- 51nod 1275 连续子段的差异
题目看这里 若[i,j]符合要求,那么[i,j]内的任何连续的子段都是符合要求的.我们可以枚举i,找到能合格的最远的j,然后ans+=(j-i+1). 那么问题就转换成了:在固定i的情况下,如何判断j ...
- 51Nod 1081:子段求和(前缀和)
1081 子段求和 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和 ...
- 51Nod 1049最大子段和 | 模板
Input示例 6 -2 11 -4 13 -5 -2 Output示例 20 1.最大子段和模板 #include "bits/stdc++.h" using namespace ...
- 51nod 1254 最大子段和 V2 ——单调栈
N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...
- (DP)51NOD 1049 最大子段和
N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值.当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5 ...
- 51nod 1254 最大子段和 V2
N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...
随机推荐
- 深度长文整理-Redis进阶
目录 一.基础 二.为什么Redis是单线程的? 三.为什么单线程这么快? 四.select.poll.epoll 五.Redis的事物 六.Redis的监控 七.Redis的配置文件 八.Redis ...
- hystrix源码之请求缓存
HystrixRequestCache 请求缓存.内部是一个静态ConcurrentHashMap存储各个命令的缓存器,RequestCacheKey为key,HystrixRequestCache为 ...
- 获取NX特征名称(无时间戳)
NX获取特征名称使用UF_MODL_ask_feat_name这个接口,接口说明里有一段话: Returns a character string containing the feature typ ...
- 基于redis的分布式锁的实现与框架解决方案
利用切面实现redis分布式锁:https://www.cnblogs.com/xiaoxiongcanguan/p/10718202.html 细节分析redis实现分布式锁的前因后果:https: ...
- 基础篇:Object对象
目录 1 Object的内存结构和指针压缩了解一下 2 Object的几种基本方法 3 == . equals.Comparable.compareTo.Comparator.compara 四种比较 ...
- nginx 1.12 负载均衡配置
负载均衡策略有以下几种: 请求轮询:round-robin,是默认策略,应用服务器的请求以循环方式分发,可以设置权重weight,默认权重均为1,因此每台后端服务器接受的请求数相同. 最少连接:lea ...
- Centos-移动文件或目录-mv
mv 移动文件或者目录,可以用重命名文件或者目录 相关选项 -i 如果文件或目录存在询问是否覆盖,输入y确认,输入n取消 -f 不提示,覆盖
- # mac使用homebrew安装jdk和tomcat
homebrew安装jdk 前提是已经安装homebrew //直接命令行安装 brew cask install homebrew/cask-versions/adoptopenjdk8 homeb ...
- makefile实验一 make的基本原则、伪目标、以及不使用.PHONY确实现和伪目标一样功能的一种方法
target: echo "hello_Makefile" .PHONY: clean clean: echo "clean Done .2019" 使用伪目标 ...
- 072 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 04 综合案例-数组移位-在指定位置处插入数据方法
072 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 04 综合案例-数组移位-在指定位置处插入数据方法 本文知识点:综合案例-数组移位-在指定位置处插入数据方法 ...