P1886 滑动窗口 /【模板】单调队列 方法记录
滑动窗口 /【模板】单调队列
题目描述
有一个长为 \(n\) 的序列 \(a\),以及一个大小为 \(k\) 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如:
The array is \([1,3,-1,-3,5,3,6,7]\), and \(k = 3\)。
输入格式
输入一共有两行,第一行有两个正整数 \(n,k\)。
第二行 \(n\) 个整数,表示序列 \(a\)
输出格式
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
样例 #1
样例输入 #1
8 3
1 3 -1 -3 5 3 6 7
样例输出 #1
-1 -3 -3 -3 3 3
3 3 5 5 6 7
提示
【数据范围】
对于 \(50\%\) 的数据,\(1 \le n \le 10^5\);
对于 \(100\%\) 的数据,\(1\le k \le n \le 10^6\),\(a_i \in [-2^{31},2^{31})\)。
算法:单调队列
单调队列的性质
性质1:单调性
队列中的元素必须满足单调性。如果要求区间最大值,则队列单调递减;否则队列单调递增。即:队首就是要求的元素。
性质2:有序性
事实上,元素在原序列中的相对位置和在队列中的相对位置不变
我们可能进行的操作(“队列”指我们用到的单调序列,“原序列”指输入的序列)
一.当队列中无元素时,直接将原序列中的元素从队尾入队;
二.当队列中有元素时,面对即将进入的元素,若队列中的元素小于即将进入的元素,则队列中的元素不可能成为窗口中的最小值,队列中的元素从队尾出队,新元素从队尾入队。这样以来,队列中的元素就保证是单调递增的;
三.当有新元素进入时,由于不知道之后进入的元素是否比它小,那么这个元素依然有可能成为窗口中的最小值;
四.模拟窗口滑动:如果当前遍历位置与队首位置的区间大于窗口,则重复执行队首右移;
五.生成答案:当遍历的位置第一次超过窗口大小时,每遍历一个元素就会生成一个答案。由于维护的队列单调递增,则每次队首元素就是答案。
程序上的操作参见代码注释。
点击查看代码
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1000005;
int n,k,h,t;
int a[N],q1[N],q2[N];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//t--队尾出,h++队首出,t++队尾进
//q1[],q2[]储存的都是位置,只有a[]储存的是值
for(int i=1;i<=n;i++)
{
while(h<=t&&i-q1[h]>=k) h++;
while(h<=t&&a[i]<a[q1[t]]) t--;
q1[++t]=i;
if(i>=k) printf("%d ",a[q1[h]]);
}
puts("");
for(int i=1;i<=n;i++)
{
while(h<=t&&i-q2[h]>=k) h++;
while(h<=t&&a[i]>a[q2[t]]) t--;
q2[++t]=i;
if(i>=k) printf("%d ",a[q2[h]]);
}
return 0;
}
参考:
https://blog.csdn.net/qaqwqaqwq/article/details/120429563
https://www.luogu.com.cn/blog/hankeke/solution-p1886
P1886 滑动窗口 /【模板】单调队列 方法记录的更多相关文章
- luogu P1886 滑动窗口(单调队列
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- P1886 滑动窗口(单调队列)
P1886 滑动窗口 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: ...
- 洛谷 P1886 滑动窗口(单调队列)
嗯... 题目链接:https://www.luogu.org/problem/P1886 首先这道题很典型,是标准的单调队列的模板题(也有人说单调队列只能解决这一个问题).这道题可以手写一个队列,也 ...
- luoguP1886 滑动窗口(单调队列模板题)
题目链接:https://www.luogu.org/problem/P1886#submit 题意:给定n个数,求大小为k的滑动窗口中最小值和最大值. 思路:单调队列模板题. AC代码: #incl ...
- 【P1886】滑动窗口(单调队列→线段树→LCT)
这个题很友好,我们可以分别进行简单难度,中等难度,恶心难度来做.然而智商没问题的话肯定是用单调队列来做... 板子题,直接裸的单调队列就能过. #include<iostream> #in ...
- poj2823滑动窗口(单调队列)
题目传送门 题意:给你一个长度为n的数列,然后用一个长度为k的窗口去框(k<n)每次保存k这个窗口中的最大值和最小值,输出. 思路:这道题最朴素的on2的做法铁定超时,然后我想过一个nlogn的 ...
- POJ2823 滑动窗口 (单调队列)
来学习一下单调队列: 他只可以从队尾入队,但可以从队尾或队首出队,来维护队列的单调性.单调队列有两种单调性:元素的值单调和元素的下标单调. 单调队列可以用来优化DP.状态转移方程形如dp[i]=min ...
- [luoguP1866]滑动窗口(单调队列)
传送门 可以搞2个单调队列. 然后,然后就没有然后了. # include <iostream> # include <cstdio> # include <cstrin ...
- 单调队列优化&&P1886 滑动窗口题解
单调队列: 顾名思义,就是队列中元素是单调的(单增或者单减). 在某些问题中能够优化复杂度. 在dp问题中,有一个专题动态规划的单调队列优化,以后会更新(现在还是太菜了不会). 在你看到类似于滑动定长 ...
随机推荐
- shell中各种括号的用法
一.单小括号()1.将某个命令的返回值作为某个变量的值进行传递 #!/bin/bash USER=$(whoami) echo $USER [root@jump ~]# for i in $(seq ...
- Thread类的常用方法_获取线程名称的方法和Thread类的常用方法_设置线程名称的方法
构造方法: public Thread();分配一个新的线程对象 public Thread(String name);分配一个指定名字的新的线程对象 public Thread(Runnable t ...
- python 操作xml、html文件
简介 在一些项目中可能会使用到解析html文件,尤其是爬虫相关的,需要解析获取到的html内容,通常我们会使用lxml模块去进行html文件的解析. html文件 当前存在一个简单的html < ...
- JS for in / foreach / for of 超简单对照解释
for in 可以遍历数组/对象/字符串/enumerable对象,得到的是索引,遍历对象时可以写这样 obj[index] 代表对象当前的属性foreach 只能遍历数组,不能遍历字符串.对象for ...
- Javascript 函数声明、调用、闭包
1 # Javascript 函数声明.调用.闭包 2 # 一.函数声明 3 # 1.直接声明.浏览器在执行前,会先将变量和函数声明进行提升. 4 fn(); 5 function fn () { 6 ...
- 利用 SonarScanner 静态扫描 Rainbond 上的 Maven 项目
对代码进行静态扫描是一种非常常见的代码质量保证手段,这种扫描不仅仅可以检查到代码中的缺陷,应用各种业界最佳实践,也可以检查出安全方面的漏洞,给予项目代码全方位的提升.在各种代码扫描方案之中,Sonar ...
- [算法1-排序](.NET源码学习)& LINQ & Lambda
[算法1-排序](.NET源码学习)& LINQ & Lambda 说起排序算法,在日常实际开发中我们基本不在意这些事情,有API不用不是没事找事嘛.但必要的基础还是需要了解掌握. 排 ...
- Docker 04 容器命令
参考源 https://www.bilibili.com/video/BV1og4y1q7M4?spm_id_from=333.999.0.0 https://www.bilibili.com/vid ...
- Unity 将是驱动 C# 增长的引擎吗 ?
C# 在中国的采用需要一个杀手级应用的带动, 那么这样的一个杀手级应用是 Unity吗,我这里大胆推测采用CoreCLR 的新一代完全采用C#构建的Unity 将是这样的一个杀手级应用.Unity已被 ...
- 逐层阅读 research paper:Dmitry Berenson 的方法论
本博客翻译了 这篇文章,包含很实用的 读论文的方法论. 读论文的四个 layers 在读论文之前,要首先搞清楚,自己读论文的目的是什么,或者 希望读到什么程度. 下表列出了常见的读论文目的,以及相应的 ...