洛谷 P1886 滑动窗口(单调队列)
题目链接
https://www.luogu.org/problemnew/show/P1886
题目描述
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如:
The array is [1 3 -1 -3 5 3 6 7], and k = 3.
输入输出格式
输入格式:
输入一共有两行,第一行为n,k。
第二行为n个数(<INT_MAX).
输出格式:
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
输入输出样例
8 3
1 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 3
3 3 5 5 6 7
说明
50%的数据,n<=10^5
100%的数据,n<=10^6
解题思路
先理解文意:对于给定一个长度为n的序列,找出所有长为k的区间的最大值(最小值)。
首先很多人会想到,枚举每一个长为k的区间,然后遍历一遍,找到最大值(最小值),这样的时间复杂度是o(nk)的,显然超时。
所以我们需要换一种思路。
单调队列:单调队列就是一个一直保持单调性(递增或递减)的长度最大为k的双端队列。
我们维护这样一个单调队列,使它队首元素即为要求的最大值(最小值)。
所以本题的核心是:怎样维护一个单调队列。
在此举例求最大值:对于任意读入的元素,我们不放设为in,首先判断队列是否为空,如果队列为空,就一定要加入队列。若不为空,就一直比较队列末尾的元素,不放设为f,如果f<in,就把f弹出去,砍掉。为什么呢?因为f能做到的,in一定也能做到,in>f,所以在一定范围内,答案有可能是in,但永远不可能是f。(这里有一个有趣的类比,如果一位OIer比你年轻还比你强,那你就没法超越他了。——Kevin大佬)。还有一个问题,就是滑动窗口长度最大是k,所以我们需要用结构体保存每一个数的编号和数值,如果in的编号和队首的编号的差>=k,就把队首砍掉,这是显然的。
这样,由于每一个元素只进入队列一次,所以时间复杂度就变成o(n)了。
话不多说,看代码。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<ctime> //还是写了一大堆没用的头文件
using namespace std;
int n,k;
int maxx[],minn[]; //由于输出要求,需要先用数组存好答案
struct num{ //结构体储存编号和数值
int cnt,value;
num(int a,int b):cnt(a),value(b){} //结构体构造函数,作用是在定义结构体的时候,就会给cnt和value赋值。用法具体看29行或者39行代码
};
deque<num> q1,q2; //定义两个双端队列,q1储存最大值,q2储存最小值
void makeq1(int i,int in){ //makeq1处理最大值
if(q1.empty()) q1.push_back(num(i,in));//队列为空时直接入队
else{
num f=q1.front();
if(i>f.cnt+k-) q1.pop_front();//判断队列长度是否超过k
if(!q1.empty()){ //队尾弹不断弹出操作
num b=q1.back();
while(b.value<in){
q1.pop_back();
if(q1.empty()) break;
b=q1.back();
}
}
q1.push_back(num(i, in));
}
}
void makeq2(int i,int in){ //makeq2处理最小值
if(q2.empty()) q2.push_back(num(i,in));//队列为空时直接入队
else{
num f=q2.front();
if(i>f.cnt+k-) q2.pop_front(); //判断队列长度是否超过k
if(!q2.empty()){ //队尾弹不断弹出操作
num b=q2.back();
while(b.value>in){ //和makeq1不同的地方
q2.pop_back();
if(q2.empty()) break;
b=q2.back();
}
}
q2.push_back(num(i, in));
}
}
int main()
{
cin>>n>>k;
for(int i=;i<=n;i++){
int in;
cin>>in;
makeq1(i,in);
makeq2(i,in);
if(i>=k){ //如果长度达到k,就储存结果
maxx[i]=q1.front().value;
minn[i]=q2.front().value;
}
}
for(int i=k;i<=n;i++) cout<<minn[i]<<" "; //注意输出格式
cout<<endl;
for(int i=k;i<=n;i++) cout<<maxx[i]<<" ";
return ;
}
AC代码
洛谷 P1886 滑动窗口(单调队列)的更多相关文章
- [洛谷P1886]滑动窗口 (单调队列)(线段树)
---恢复内容开始--- 这是很好的一道题 题目描述: 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口. 现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的 ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- 洛谷 P1886 滑动窗口(单调队列)
嗯... 题目链接:https://www.luogu.org/problem/P1886 首先这道题很典型,是标准的单调队列的模板题(也有人说单调队列只能解决这一个问题).这道题可以手写一个队列,也 ...
- 洛谷 P1886 滑动窗口
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- [Luogu P1886]滑动窗口--单调队列入门
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- 洛谷 P1886 滑动窗口 (数据与其他网站不同。。)
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- 洛谷——P1886 滑动窗口|| POJ——T2823 Sliding Window
https://www.luogu.org/problem/show?pid=1886#sub || http://poj.org/problem?id=2823 题目描述 现在有一堆数字共N个数字( ...
- 洛谷P1886--滑动窗口(单调队列模板)
https://www.luogu.org/problemnew/show/P1886 单调队列的操作上比普通队列多了可以从尾端出队 单调队列保持队内元素单调递增/递减,以保证队首元素为最小/最大元素 ...
- [POJ2823][洛谷P1886]滑动窗口 Sliding Window
题目大意:有一列数,和一个窗口,一次能框连续的s个数,初始时窗口在左端,不断往右移动,移到最右端为止,求每次被框住的s个数中的最小数和最大数. 解题思路:这道题是一道区间查询问题,可以用线段树做.每个 ...
随机推荐
- 学Python的第六天
今天发愤图强,死学Python!!!! 为此小编还买了自己喜欢的McPython! 从小老师就说兴趣是最好的老师,所以呢买这本书是想通过我的世界这款游戏来提高自己的学习兴趣!!! 当然也有私心啦... ...
- thinkphp数据库连接
https://www.kancloud.cn/manual/thinkphp5/118059 一.配置文件定义 常用的配置方式是在应用目录或者模块目录下面的database.php中添加下面的配置参 ...
- CSS多列布局(栅格布局)
一.多列布局 CSS3 可以将文本内容设计成像报纸一样的多列布局,如下实例: 代码如下(具体的解释也在代码中)浏览器支持表格中的数字表示支持该方法的第一个浏览器的版本号. 紧跟在数字后面的 -webk ...
- vue 打包上线后 所使用的css3渐变属性丢失的问题解决方案
最近在做vue项目的时候用到了css3渐变属性,本地跑项目没问题,但是打包放到服务器后发现这个属性丢失了.如下图: .join{ position:absolute; left:1rem; botto ...
- 使用rabbitctl添加用户
使用rabbitctl添加用户 第一.添加mq用户并设置密码 root@live-mq-01:~ # rabbitmqctl add_user mq 123456 1 root@live-mq-01: ...
- windows下zookeeper集群安装
windows下zookeeper单机版安装,见:https://www.cnblogs.com/lbky/p/9867899.html 一:zookeeper节点为什么是奇数个? 单机模式的zk进程 ...
- JS中判断一个数组是否有相同数据的
页面中有多个<select> $("select").each(function(){ str.push($(this).val());}); // join() 方法 ...
- 考研结束-开启新生活---markdown语法
markdown语法 考研结束,正式开始提高自己的技术储备. 第一步当然是找到自己原先的博客园,记录下自己的足迹 将博客园设置为markdown编辑器 找到一篇关于markdown的语法介绍 原博文链 ...
- UVa 10054 : The Necklace 【欧拉回路】
题目链接 题目大意:我的妹妹有一串由各种颜色组成的项链. 项链中两个连续珠子的接头处共享同一个颜色. 如上图, 第一个珠子是green+red, 那么接这个珠子的必须以red开头,如图的red+whi ...
- django2 + python3 显示静态文件中的图片
之前一直搞不出来 是因为图片的问题,步骤也就是固定的几步,到位了就差不多成了 文件夹结构: . ├── HelloWorld │ ├── __init__.py │ ├── __pycache ...