我在知乎上看到一句话,如一道晴天霹雳:

“如果一个选手比你小还比你强,你就可以退役了。”——单调队列的原理

题意

link(more:P1714

给定一个长度为 \(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.最大子序和【单调队列】的更多相关文章

  1. CH1201 最大子序和 (单调队列)

    题目链接: AcWing 牛客 题目描述 输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当 ...

  2. CH 1201 - 最大子序和 - [单调队列]

    题目链接:传送门 描述输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大. 例如 $1,-3,5,1,-2,3$. 当 $m=4$ 时,$S=5+1-2+3=7$:当 ...

  3. AcWing:135. 最大子序和(前缀和 + 单调队列)

    输入一个长度为n的整数序列,从中找出一段长度不超过m的连续子序列,使得子序列中所有数的和最大. 输入格式 第一行输入两个整数n,m. 第二行输入n个数,代表长度为n的整数序列. 同一行数之间用空格隔开 ...

  4. hdu 6319 逆序建单调队列

    题目传送门//res tp hdu 维护递增单调队列 根据数据范围推测应为O(n)的. 我们需要维护一个区间的信息,区间内信息是"有序"的,同时需要在O(1)的时间进行相邻区间的信 ...

  5. 单调栈&单调队列学习笔记!

    ummm,,,都是单调系列就都一起学了算了思想应该都差不多呢qwq 其实感觉这俩没有什么可说的鸭QAQ就是维护一个单调的东西,区别在于单调栈是一段进一段出然后单调队列是一段进另一段出?没了 好趴辣重点 ...

  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 输 ...

  7. 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 输入 ...

  8. 【动态规划】【单调队列】tyvj1305 最大子序和

    http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include< ...

  9. tyvj1305 最大子序和(单调队列

    题目地址:http://www.joyoi.cn/problem/tyvj-1305 最大子序和 题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Loc ...

随机推荐

  1. P5657 [CSP-S2019] 格雷码 (找规律)

    观察几个数据,有一种思路:类似于二分,判断每一位应该填1还是0: 1 #include <bits/stdc++.h> 2 //#define loveGsy 3 using namesp ...

  2. 《Vue3.x+TypeScript实践指南》已出版

    转眼回长沙快2年了,图书本在去年就已经完稿,因为疫情,一直耽搁了,直到这个月才出版!疫情之下,众生皆苦!感觉每天都是吃饭.睡觉.上班.做核酸! 图书介绍 为了紧跟技术潮流,该书聚焦于当下火的Vue3和 ...

  3. 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 ...

  4. 记录一次使用git工具拉取coding上代码密码账号错误的经历

    1.忘记密码 1.另外的一个位置

  5. Codeforces Round #751 (Div. 2)/CodeForces1602

    CodeForces1602 Two Subsequences 解析: 题目大意 给你一个字符串 \(s\).你需要两个非空字符串 \(a\) 和 \(b\) 并且满足下面的条件: 字符串 \(a\) ...

  6. 虚拟机里网络连接的几种方式说明(桥接,NAT, 仅主机)

    虚拟机里网络连接类型的选择: 桥接:选择桥接模式的话虚拟机和宿主机在网络上就是平级的关系,相当于连接在同一交换机上. NAT:NAT模式就是虚拟机要联网得先通过宿主机才能和外面进行通信. 仅主机:虚拟 ...

  7. Log4shell漏洞研究及其挖矿案例分析

    本文首发于云影实验室,为本人创作,现转载到个人博客,记录一下. 原文链接:https://mp.weixin.qq.com/s/O2xHr2OEHiga-qTnbWTxQg Apache Log4j是 ...

  8. ES6 学习笔记(九)Set的基本用法

    1 基本用法 set类似于数组,它的成员是唯一的,当有多个相同的值,只会保留一份. 1.1 创建方法 Set本身是一个构造函数,用来生成Set实例,如: const s = new Set() let ...

  9. 从 QFramework 重新开始

    自从上一篇博文写完后,就进入了繁忙工作状态,直到最近才开始有一点空闲时间. 这次繁忙的状态从 2022 年 10 月 11 日 持续到 2022 年 11 月 5 日. 主要的工作就是 QFramew ...

  10. C语言算法入门

    2018年11月2日  leetcode的确是一个不错的网站,希望能提升自己的算法力 int* twoSum(int* nums, int numsSize, int target) { } 出现的第 ...