[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 ...
随机推荐
- P5657 [CSP-S2019] 格雷码 (找规律)
观察几个数据,有一种思路:类似于二分,判断每一位应该填1还是0: 1 #include <bits/stdc++.h> 2 //#define loveGsy 3 using namesp ...
- 《Vue3.x+TypeScript实践指南》已出版
转眼回长沙快2年了,图书本在去年就已经完稿,因为疫情,一直耽搁了,直到这个月才出版!疫情之下,众生皆苦!感觉每天都是吃饭.睡觉.上班.做核酸! 图书介绍 为了紧跟技术潮流,该书聚焦于当下火的Vue3和 ...
- Can not set int field xxx to java.lang.Long 错误
Can not set int field xxx to java.lang.Long 错误 这个错误其实是因为Java程序和MySQL表中字段的属性匹配不一致 我的报错是Can not set ja ...
- 记录一次使用git工具拉取coding上代码密码账号错误的经历
1.忘记密码 1.另外的一个位置
- Codeforces Round #751 (Div. 2)/CodeForces1602
CodeForces1602 Two Subsequences 解析: 题目大意 给你一个字符串 \(s\).你需要两个非空字符串 \(a\) 和 \(b\) 并且满足下面的条件: 字符串 \(a\) ...
- 虚拟机里网络连接的几种方式说明(桥接,NAT, 仅主机)
虚拟机里网络连接类型的选择: 桥接:选择桥接模式的话虚拟机和宿主机在网络上就是平级的关系,相当于连接在同一交换机上. NAT:NAT模式就是虚拟机要联网得先通过宿主机才能和外面进行通信. 仅主机:虚拟 ...
- Log4shell漏洞研究及其挖矿案例分析
本文首发于云影实验室,为本人创作,现转载到个人博客,记录一下. 原文链接:https://mp.weixin.qq.com/s/O2xHr2OEHiga-qTnbWTxQg Apache Log4j是 ...
- ES6 学习笔记(九)Set的基本用法
1 基本用法 set类似于数组,它的成员是唯一的,当有多个相同的值,只会保留一份. 1.1 创建方法 Set本身是一个构造函数,用来生成Set实例,如: const s = new Set() let ...
- 从 QFramework 重新开始
自从上一篇博文写完后,就进入了繁忙工作状态,直到最近才开始有一点空闲时间. 这次繁忙的状态从 2022 年 10 月 11 日 持续到 2022 年 11 月 5 日. 主要的工作就是 QFramew ...
- C语言算法入门
2018年11月2日 leetcode的确是一个不错的网站,希望能提升自己的算法力 int* twoSum(int* nums, int numsSize, int target) { } 出现的第 ...