51nod 最大M子段和系列
第1行:2个数N和M,中间用空格分隔。N为整数的个数,M为划分为多少段。(2 <= N , M <= 5000)
第2 - N+1行:N个整数 (-10^9 <= a[i] <= 10^9)
输出这个最大和
7 2
-2
11
-4
13
-5
6
-2
26
———————————————————————————————————
1254 最大子段和 V2
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N + 1行:N个整数(-10^9 <= A[i] <= 10^9)
输出交换一次后的最大子段和。
7
-2
11
-4
13
-5
-2
4
28
——————————————————————————
因为这两道题是一种写法所以我就写在一起
就把连续的一段正负的合在一起得到一段正负相间的序列
然后记录一共有多少个正的记为tot 题目要保留的段数记为 k
那么我们就需要消掉tot-k份 消掉的方法有放弃某一段正的或者是用一段负的把两段正的合并
这样我们维护一个堆 权值是需要付出的代价 这样慢慢合并就能解决问题了
记得记录每一段的相邻段就好辣 当然记得特判边界 我的处理方法是加一段权值为负无穷的段就好辣
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const int M=1e6+1e5+;
const LL inf=1e15;
LL read(){
LL ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
int n,k,f[M],lx[M],rx[M];
LL cnt,sum[M],v,ans;
bool pd(LL x,LL y){return !x||!y||(x>)==(y>);}
LL pabs(LL x){return x>=?x:-x;}
struct node{
LL w,pos;
bool operator <(const node& x)const{return x.w<w;}
};
priority_queue<node>q;
int main(){
n=read(); k=read();
int h=;
while(h<=n&&(v=read())<=) h++;//printf("[%d]\n",h);
if(v>) sum[++cnt]=v;
for(int i=h+;i<=n;i++){
v=read();
if(pd(sum[cnt],v)) sum[cnt]+=v;
else sum[++cnt]=v;
}
if(pd(sum[cnt],-inf)) sum[cnt]+=-inf;
else sum[++cnt]=-inf;
int tot=; for(int i=;i<=cnt;i++)if(sum[i]>=) ans+=sum[i],tot++;
if(tot<=k) return printf("%lld\n",ans),;
int now=tot-k;
for(int i=;i<=cnt;i++) q.push((node){pabs(sum[i]),i}),lx[i]=i-,rx[i]=i+;
lx[]=cnt; rx[cnt]=;
while(now){
node x=q.top(); q.pop();
int k=x.pos;
if(f[k]) continue;
ans-=x.w; now--;
LL l=lx[k],r=rx[k];
f[l]=; f[r]=;
sum[++cnt]=sum[k]+sum[l]+sum[r];
q.push((node){pabs(sum[cnt]),cnt});
lx[cnt]=lx[l]; rx[cnt]=rx[r];
rx[lx[l]]=cnt; lx[rx[r]]=cnt;
}
printf("%lld\n",ans);
return ;
}
第1行:2个数N和M,中间用空格分隔。N为整数的个数,M为划分为多少段。(2 <= N , M <= 100000)
第2 - N+1行:N个整数 (-10^9 <= a[i] <= 10^9)
输出这个最大和
7 2
-2
11
-4
13
-5
6
-2
26
————————————————————————
这道题不需要特判边界反而更容易QAQ
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstdlib>
#define LL long long
using namespace std;
const int M=;
LL read(){
LL ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
LL lx[M],rx[M],w[M];
LL n,k,tot;
LL cnt=;
LL sum[M],ans;
bool f[M];
struct node{
LL w,pos;
bool operator<(const node &x) const{return w>x.w;}
};
priority_queue<node>q;
LL pd(LL x){return x>=?x:-x;}
bool okay(LL a,LL b){return (a<&&b<)||(a>&&b>)||!a||!b;}
int main()
{
LL v;
n=read(); k=read();
for(int i=;i<=n;i++){
v=read();
if(okay(sum[cnt],v)) sum[cnt]+=v;
else sum[++cnt]=v;
}
if(okay(sum[],sum[cnt])) sum[]=sum[cnt]+sum[],cnt--;
for(int i=;i<=cnt;i++)
if(sum[i]>) ans+=sum[i],tot++;
if(tot<=k){printf("%lld\n",ans); return ;}
LL now=tot-k;
q.push((node){pd(sum[]),});
lx[]=cnt; rx[]=; w[]=pd(sum[]);
q.push((node){pd(sum[cnt]),cnt});
lx[cnt]=cnt-; rx[cnt]=; w[cnt]=pd(sum[cnt]);
for(int i=;i<cnt;i++)
q.push((node){pd(sum[i]),i}),lx[i]=i-,rx[i]=i+,w[i]=pd(sum[i]);
while(now){
node x=q.top(); q.pop();
LL k=x.pos;
if(f[k]) continue;
ans-=w[k]; now--;
LL l=lx[k],r=rx[k];
f[l]=; f[r]=;
cnt++;
sum[cnt]=sum[k]+sum[l]+sum[r];
w[cnt]=pd(sum[cnt]);
q.push((node){w[cnt],cnt});
lx[cnt]=lx[l]; rx[cnt]=rx[r];
rx[lx[l]]=cnt; lx[rx[r]]=cnt;
}
printf("%lld\n",ans);
return ;
}
51nod 最大M子段和系列的更多相关文章
- 51Nod 最大M子段和系列 V1 V2 V3
前言 \(HE\)沾\(BJ\)的光成功滚回家里了...这堆最大子段和的题抠了半天,然而各位\(dalao\)们都已经去做概率了...先%为敬. 引流之主:老姚的博客 最大M子段和 V1 思路 最简单 ...
- 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 段 ...
- 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]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...
随机推荐
- python 快速搭建文件服务器
以http方式共享当前文件夹的文件 可实现跨平台文件传输 只需要一句话搞定 #python -m SimpleHTTPServer 8001 浏览器中输入 http://ip:8001 显示所有文件 ...
- 怎么防止别人动态在你程序生成代码(怎么防止别人反编译你的app)
1.本地数据加密 iOS应用防反编译加密技术之一:对NSUserDefaults,sqlite存储文件数据加密,保护帐号和关键信息 2.URL编码加密 iOS应用防反编译加密技术之二:对程序中出现的U ...
- java集合浅谈(一)
一.类库结构图概览 容器对象仅能持有对象引用(对象的指针),而不是Copy对象信息,从网上搜得几张Java中集合类库的结构图,如下所示: 二.解说Collection 2.1 Collection ( ...
- Google序列化库FlatBuffers 1.1发布,及与protobuf的比较
个人总结: FlatBuffer相对于Protobuffer来讲,优势如下: 1. 由于省去了编解码的过程,所以从速度上快于Protobuffer,个人测试结果100w次编解码,编码上FlatBuff ...
- java.sql.Date java.sql.Time java.sql.Timestamp 之比较
java.sql.Date,java.sql.Time和java.sql.Timestamp 三个都是java.util.Date的子类(包装类). java.sql.Date是java.util.D ...
- 孤荷凌寒自学python第七十四天开始写Python的第一个爬虫4
孤荷凌寒自学python第七十四天开始写Python的第一个爬虫4 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 直接上代码.详细过程见文末屏幕录像 ...
- BZOJ 3670 NOI2014 动物园 KMP+dp
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3670 题意概述:令num[i]表示字符串由1~i的字符形成的前缀中不相重叠的相同前后缀的数 ...
- POJ 3076 / ZOJ 3122 Sudoku(DLX)
Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells ...
- POJ 1463 Strategic game(二分图最大匹配)
Description Bob enjoys playing computer games, especially strategic games, but sometimes he cannot f ...
- kafka卡顿
一次kafka卡顿事故排查过程 https://www.cnblogs.com/yougewe/p/8975550.html 由于一次功能上线后,导致某数据量急剧下滑,给我们紧张的呢!排查过程也是个学 ...