[0x12] 135.最大子序和【单调队列】
我在知乎上看到一句话,如一道晴天霹雳:
“如果一个选手比你小还比你强,你就可以退役了。”——单调队列的原理
题意
给定一个长度为 \(n\) 的整数序列,从中找出一段长度不超过 \(m\) 的子串,使得子串中所有数的和最大。
其中, \(n,m\leqslant 3\times 10^5\) 。
思路
首先要计算区间和,易想到预处理前缀和( \(s[i]=\sum\limits_{j=1}^ia[j],s[0]=0\) ),那么问题可以转化为:找出两个端点 \(l,r(r-l\leqslant m)\) ,使 \(s[r]-s[l]\) 最大。
我们可以先枚举右端点 \(r\) ( \(l\) 也就随之确定),当 \(r\) 固定时,肯定希望 \(s[l]\) 越小越好,问题又可转化为:找出左端点 \(l(l\in[i-m,i-1])\) ,使 \(s[l]\) 最小。
由此,可以易想到一个 \(O(nm)\) 的算法,但显然超时,∵我们把所有情况都进行处理,其实所有 \([i-m,i-1]\) 区间内大于最小值的数都是无用的,但又不可能对区间排序。(属于是火上浇油)
那我们就希望把区间值放到另一个结构里计算,以较高的效率从中得到最小值,且要符合 \(r\) 不断右移,从右边进新值,并从左边出旧值,还要保持单调性。
∴想到用 \(\boxed{单调队列}\) 来维护区间。
假设序列为 \(\{1,-3,5,1,-2,-3\}\) ,则 \(s=\{1,-2,3,4,2,5\}\) 。
已知队列是先进先出的顺序,我们要使进来的值单调(例如可以单调递增),那么我们抽象对比一下两个值 \(x,y\) ,且按顺序进队。如果 \(x\geqslant y\) ,那么 \(x\) 完全就没有用了,把它弹出,继续按照这个逻辑,如图:

(为便于形象展示,单调队列图中存值,实际代码中,为方便调用,存对应下标)
维护时有两种操作:
- 队头需要弹出值,超过长度限制的值弹出。
- 队尾需要加入值,不断将前面大于自己的数删掉。
可见,维护时每个点最多进队、出队一次,总的时间复杂度就降到了 \(O(n)\) 。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
int n,m;
int Q[N],h,t;
ll s[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
s[i]=s[i-1]+x;
}
ll ans=LLONG_MIN;
for(int i=1;i<=n;i++)
{
while(h<=t && Q[h]<i-m) h++;
ans=max(ans,s[i]-s[Q[h]]);
while(h<=t && s[Q[t]]>=s[i]) t--;
Q[++t]=i;
}
cout<<ans;
return 0;
}
总结
单调队列的思想:在决策集合(队列)中及时排除一定不是最优解的选择。
[0x12] 135.最大子序和【单调队列】的更多相关文章
- CH1201 最大子序和 (单调队列)
题目链接: AcWing 牛客 题目描述 输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当 ...
- CH 1201 - 最大子序和 - [单调队列]
题目链接:传送门 描述输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大. 例如 $1,-3,5,1,-2,3$. 当 $m=4$ 时,$S=5+1-2+3=7$:当 ...
- AcWing:135. 最大子序和(前缀和 + 单调队列)
输入一个长度为n的整数序列,从中找出一段长度不超过m的连续子序列,使得子序列中所有数的和最大. 输入格式 第一行输入两个整数n,m. 第二行输入n个数,代表长度为n的整数序列. 同一行数之间用空格隔开 ...
- hdu 6319 逆序建单调队列
题目传送门//res tp hdu 维护递增单调队列 根据数据范围推测应为O(n)的. 我们需要维护一个区间的信息,区间内信息是"有序"的,同时需要在O(1)的时间进行相邻区间的信 ...
- 单调栈&单调队列学习笔记!
ummm,,,都是单调系列就都一起学了算了思想应该都差不多呢qwq 其实感觉这俩没有什么可说的鸭QAQ就是维护一个单调的东西,区别在于单调栈是一段进一段出然后单调队列是一段进另一段出?没了 好趴辣重点 ...
- tyvj1305 最大子序和 【单调队列优化dp】
描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当m=2或m=3时,S=5+1=6 输 ...
- Tyvj1305最大子序和(单调队列优化dp)
描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7当m=2或m=3时,S=5+1=6 输入 ...
- 【动态规划】【单调队列】tyvj1305 最大子序和
http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include< ...
- tyvj1305 最大子序和(单调队列
题目地址:http://www.joyoi.cn/problem/tyvj-1305 最大子序和 题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Loc ...
随机推荐
- PHP全栈开发(九):javascript 基础
js不允许读取电脑上的文件: js不允许修改服务器上的文件,修改服务器上的文件是php来做的事情. 因此js是一个前端脚本. 前端的三个语言是HTML/CSS/JavaScript 这三个东东Java ...
- (数据科学学习手札144)使用管道操作符高效书写Python代码
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,一些比较熟悉pandas的读者 ...
- [Go疑难杂症]为什么nil不等于nil
现象 在日常开发中,可能一不小心就会掉进 Go 语言的某些陷阱里,而本文要介绍的 nil ≠ nil 问题,便是其中一个,初看起来会让人觉得很诡异,摸不着头脑. 先来看个例子: type Custom ...
- .Net Core&RabbitMQ限制循环消费
前言 当消费者端接收消息处理业务时,如果出现异常或是拒收消息将消息又变更为等待投递再次推送给消费者,这样一来,则形成循环的条件. 循环场景 生产者发送100条消息到RabbitMQ中,消费者设定读取到 ...
- DQL-聚合函数
DQL-聚合函数 SQL基本函数,聚合函数对一组值执行计算,并返回单个值,也被称为组函数. 聚合函数对一组值执行计算并返回单一的值.除 COUNT 以外,聚合函数忽略空值,如果COUNT函数的应用对象 ...
- raid 5搭建部署
raid 5搭建部署 软raid与备份 1.用四块磁盘做实验,三块盘搭建raid阵列组,有一块当作备份可以使用raid 5来搭建三块磁盘的阵列组 创建命令如下: [root@xiaohaoge ~]# ...
- Java多线程-线程生命周期(一)
如果要问我Java当中最难的部分是什么?最有意思的部分是什么?最多人讨论的部分是什么?那我会毫不犹豫地说:多线程. Java多线程说它难,也不难,就是有点绕:说它简单,也不简单,需要理解的概念很多,尤 ...
- 表驱动法在STM32中的应用
1.概念 所谓表驱动法(Table-Driven Approach)简而言之就是用查表的方法获取数据.此处的"表"通常为数组,但可视为数据库的一种体现.根据字典中的部首检字表查找读 ...
- 2022icpc新疆省赛
菜鸡第一次打icpc 记录一下历程 习惯#define int long long 以下皆是按照我认为的难易顺序排序 K. 看题意大概就是说求从L加到R 1 ios::sync_with_stdio( ...
- kubernetes之kubectl与YAML详解1
k8s集群的日志,带有组件的信息,多看日志. kubectl命令汇总 kubectl命令汇总 kubectl命令帮助信息 [root@mcwk8s04 ~]# kubectl -h kubectl c ...