[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 ...
随机推荐
- 洛谷P2880 [USACO07JAN] Balanced Lineup G(树状数组/线段树)
维护区间最值的模板题. 1.树状数组 1 #include<bits/stdc++.h> 2 //树状数组做法 3 using namespace std; 4 const int N=5 ...
- 基于docker安装phpmyadmin
今天用到了phpadmin,要从头装的话,比较麻烦,所以就选择使用docker 安装 准备 任意Linux系统且已成功安装docker环境 安装phpmyAdmin 1. 拉取镜像 docker pu ...
- 使用thymeleaf将查询的数据显示在前台。通过使用循环的形式
1.需要注意的点. 在 <tr th:each="book:${bookList}">中.book是自己命令的变量.${bookList}是将查询的数据放入这里,需要后 ...
- 学生管理系统(C语言简单实现)
仅供借鉴.仅供借鉴.仅供借鉴(整理了一下大一C语言每个章节的练习题.没得题目.只有程序了) 文章目录 1 .实训名称 2.实训目的及要求 3. 源码 4.实验小结 1 .实训名称 实训12:文件 2. ...
- 两个行内元素在一起,会出现一定的间距,即使将border、padding、margin都设置为零也无济于事,那么怎么才能去除这些间距呢?
首先这里的div设置为了行内块元素,span本身为行内元素,并且设置了* {padding: 0; margin: 0;},那怎么清除元素之间的空白缝隙呢?? (1)给元素加浮动 <!DOCTY ...
- 六、模型层(ORM)
六.模型层(ORM) Django中内嵌了ORM框架,不需要直接编写SQL语句进行数据库操作,而是通过定义模型类,操作模型类来完成对数据库中表的增删改查和创建等操作. O是object,也就类对象的意 ...
- 实验6:开源控制器实———RYU
一.实验目的 1.能够独立部署RYU控制器: 2.能够理解RYU控制器实现软件定义的集线器原理: 3.能够理解RYU控制器实现软件定义的交换机原理. 二.实验环境 Ubuntu 20.04 Deskt ...
- MongoDB - 简单了解
什么是 NoSQL NoSQL 是一种非关系型数据库管理系统,不需要固定的架构,可以避免 JOIN 连接,并且易于扩展. NoSQL 常用于具有庞大数据存储需求的分布式数据存储,通常是大数据和实时 W ...
- .Net Core 3.0 对 MongoDB 的多条件(两种)查询操作
前言 在日常开发中,偶尔会用到 MongoDB 的数据操作,也花费了一些时间调试,因此在此处记录一下,共同进步. 废话少说,出招吧! 正文 2.1 准备工作 首先需要引入 .Net 平台链接 Mo ...
- OpenMP 教程(一) 深入人剖析 OpenMP reduction 子句
OpenMP 教程(一) 深入人剖析 OpenMP reduction 子句 前言 在前面的教程OpenMP入门当中我们简要介绍了 OpenMP 的一些基础的使用方法,在本篇文章当中我们将从一些基础的 ...