单调队列
单调队列有两个性质:
1.队列中元素其对应在原列表中的位置为单调递增的。
2.队列中的元素为单调递增或单调递减。
单调队列不同于普通队列的操作是:单调队列可以同时从队首及队位弹出元素,从而维护队列单调性
那么熟悉stl的小伙伴可以迅速想到,我们可以利用双端队列(deque)来实现这个过程
以下为单调队列代码,代码中有具体解释。(题目链接https://www.luogu.com.cn/problem/P1886)
#include <cstdio>
#include <deque>//双端队列头文件
#define Maxn 1000005
using namespace std;
struct node{
int num,val;
};//记录每一个元素在原序列中对应的下标及大小
deque<node>q1,q2;
int n,k,cnt;
int ans[3][Maxn];//ans[1][]记录最大值 ans[2][]记录最小值
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
while(!q1.empty()&&i-k>=q1.front().num) q1.pop_front();
while(!q2.empty()&&i-k>=q2.front().num) q2.pop_front();//如果队列不为空且队首元素的下标位置超出了当前所需查找的范围,队首弹出
node now;
now.num=i,now.val=x;//记录当前元素大小及下标
while(!q1.empty()&&x>=q1.back().val) q1.pop_back();//如果队尾元素小于当前元素,队尾弹出,因为q1存储的是最大值,是一个单调递减序列
while(!q2.empty()&&x<=q2.back().val) q2.pop_back();//如果队尾元素大于当前元素,队尾弹出,因为q2存储的是最小值,是一个单调递增序列
q1.push_back(now),q2.push_back(now);//队尾压入当前元素
if(i>=k){
ans[1][++cnt]=q1.front().val;
ans[2][cnt]=q2.front().val;//此时两个队列对手存储的即为当前区间内的最大值及最小值
}
}
for(int i=1;i<=cnt;i++){
printf("%d ",ans[2][i]);
}
printf("\n");
for(int i=1;i<=cnt;i++){
printf("%d ",ans[1][i]);
}//输出
return 0;
}