单调队列优化&&P1886 滑动窗口题解
单调队列:
顾名思义,就是队列中元素是单调的(单增或者单减)。
在某些问题中能够优化复杂度。
在dp问题中,有一个专题动态规划的单调队列优化,以后会更新(现在还是太菜了不会)。
在你看到类似于滑动定长度区间的类似问题时可以考虑单调队列优化。
就像这道题:P1886 滑动窗口。
一道模板题。那么我们从题目入手讲解。
首先,你看完了题。。(??)
1.暴力
朴素的入门级想法就是双重for循环枚举当前区间里的每一个元素并取min和max。
因为外层for枚举区间头,内层for枚举区间内位置,所以复杂度O(外层区间长度*内层区间长度)也就是O(nk)。这题是1e6的数据啊。。T飞了。。
2.st表
学过较为高级的数据结构的同学可能会想到线段树和st表。
其中,线段树可以O(nlogn)查询,O(nlogn)修改。st表只支持查询,但是可以O(nlogn)预处理,在这个题中,没有修改的操作,所以我们可以使用st表,相对于线段树更优。
但是计算一下,实际复杂度在两千万?。。可能过,但是我没敢试。。。qwq。一般上千万的复杂度都得看脸过了。。
所以还有更稳定的算法:
3.单调队列
复杂度O(n),为线性算法。
主角来啦!
我们定义一个双端队列q,它两端都可以任意缩短增加长度,我们尝试维护它的长度为k。
当这个窗口向右移动一格时,自然的,要进队一个元素,出队一个元素。
我们尝试保证出队的那个元素为当前区间的最大(举例子)值,那么为了维护队列的单调性,我们必须使得队头的元素要比后面的元素都大。
考虑这样一个oi俗语:有些人比你小,他还比你强,那么你就可以退役了(深有同感)!
对于当前要进队的啊a[i],如果你设一个j,保证a[j]在队中切a[j]比a[i]先入队(head<j<=tail),如果a[j]比当前a[i]小(比你强大),它还先进队(比你小),是不是就抹杀掉了a[j]当最大值的机会?
那么a[j]以及那些像a[j]一类的元素(人)都可以被弹出队列(集体退役)了。。
为什么写着写着莫名辛酸。。去世吧
这也是一个重要的基础,你一定要想懂这个道理!
于是他转化成了这样一句代码:

弹出队尾。
那么,每次只要输出队头(班里的rk1)就可以了。
代码如下:
#include<cstdio>
using namespace std;
int read()
{
char ch=getchar(),last=' ';
int ans=;
while(ch>''||ch<'')last=ch,ch=getchar();
while(ch>=''&&ch<='')ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
return last=='-'?-ans:ans;
} int n,a[],k,q[]; inline int minnn()//求最小值
{
int hea=,tai=;
for(int i=;i<=n;i++)
{
while(hea<=tai&&q[hea]+k<=i)hea++;
while(hea<=tai&&a[i]<a[q[tai]])tai--;//又小又强
q[++tai]=i;
if(i>=k)printf("%d ",a[q[hea]]);//输出rk1
}
printf("\n");
} inline int maxnn()//求最大值
{
int hea=,tai=;
for(int i=;i<=n;i++)
{
while(hea<=tai&&q[hea]+k<=i)hea++;
while(hea<=tai&&a[i]>a[q[tai]])tai--;//又小又强
q[++tai]=i;
if(i>=k)printf("%d ",a[q[hea]]);//输出rk1
}
printf("\n");
} int main(){
n=read(),k=read();
for(int i=;i<=n;i++)
{
a[i]=read();
}
minnn();
maxnn();
return ;
}
一篇辛酸的讲解。
完结。
希望自己不要退役
单调队列优化&&P1886 滑动窗口题解的更多相关文章
- 【单调队列】P1886 滑动窗口
GET 单调队列 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: Th ...
- 洛谷 P1886 滑动窗口 题解
每日一题 day26 打卡 Analysis 单调队列模板 对于每一个区间,有以下操作: 1.维护队首(就是如果你已经是当前的m个之前那你就可以被删了,head++) 2.在队尾插入(每插入一个就要从 ...
- P1886 滑动窗口(单调队列)
P1886 滑动窗口 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: ...
- 【NOIP2017】跳房子 题解(单调队列优化线性DP)
前言:把鸽了1个月的博客补上 ----------------- 题目链接 题目大意:机器人的灵敏性为$d$.每次可以花费$g$个金币来改造机器人,那么机器人向右跳的范围为$[min(d-g,1),m ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- BZOJ 1499 [NOI2005] 瑰丽华尔兹 | 单调队列优化DP
BZOJ 1499 瑰丽华尔兹 | 单调队列优化DP 题意 有一块\(n \times m\)的矩形地面,上面有一些障碍(用'#'表示),其余的是空地(用'.'表示).每时每刻,地面都会向某个方向倾斜 ...
- 洛谷 P3957 跳房子 —— 二分答案+单调队列优化DP
题目:https://www.luogu.org/problemnew/show/P3957 先二分一个 g,然后判断: 由于转移的范围是一个区间,也就是滑动窗口,所以单调队列优化: 可以先令队尾为 ...
- P1886 滑动窗口&&P1440 求m区间内的最小值
声明:下面这两个题就不要暴力了,学一学单调队列吧 推荐博文:https://www.cnblogs.com/tham/p/8038828.html 单调队列入门题 P1440 求m区间内的最小值 题目 ...
- 【单调队列优化】[CF372C] Watching Fireworks is Fun
突然发现我可能单调队列都打不来了...我太菜了... 这道题显然有$$f[i][j]=min\{f[i-1][k]+\vert j-a[i] \vert\}$$ 则$ans=\sum_{i=1}^{m ...
随机推荐
- 2019牛客暑期多校训练营(第六场)-D Move
题目链接:https://ac.nowcoder.com/acm/contest/886/D 题意:给n个物品,每个物品有一个体积值,K个箱子,问箱子的最小体积为多少可将物品全部装下. 思路:比赛时一 ...
- [转帖]IP地址和CIDR
IP地址和CIDR https://www.cnblogs.com/cocowool/p/8303795.html 感谢原作者 自己竟然忘记了 classless inter-domain route ...
- SqlServer判断表中某列是否包含中文,英文,纯数字
原文:SqlServer判断表中某列是否包含中文,英文,纯数字 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...
- php用逗号格式化数字
今日工作需要格式化数字显示当前商品价格,比如2335.32,需要格式化为2,335.32这样显示.我写了一个函数.总感觉这么简单的功能,但是却需要30多行代码来完成. <?php/**** * ...
- gitignore忽略处理
.gitignore文件内容 忽略所有文件夹 /*/ 忽略所有文件 /* 这时 git add 已经失效 需要使用 git add -f 强制添加文件进版本库 好处在于在本地添加文件文件夹时, ...
- 怎样理解 Vue 的 "Hello, World!" 代码?
直接复制以下代码到 html 文件中即可运行. <!DOCTYPE html> <html> <head> <meta charset="utf-8 ...
- 区间dp 整数划分问题
整数划分(四) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...
- O047、 Cinder 组件详解
参考https://www.cnblogs.com/CloudMan6/p/5585637.html cinder-api cinder-api 是整个Cinder 组件的门户,所有cinde ...
- 导入java web项目时 web.xml第一行报错
报错信息: Referenced file contains errors (http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd). For more infor ...
- 帝国cms 通过栏目获取某个栏目的详情
当是某个栏目的时候,获取另外一个栏目下第一篇文章的详情,否则获取当前栏目下第一篇文章的详情 <?php $classid = $GLOBALS['navclassid']; if($classi ...