单调队列模板
- 对于在队列的数来说他们都是单调的,该模板队头为队列最小值下标,队尾为队列最大值下标。
//共n个数据,k为维护的区间的长度
//遍历要处理的数据
for(int i = 0;i < n;i ++){
//队头滑出区间
while(hh <= tt && q[hh] <i - k + 1) hh ++;
//保证入队的成为当前队列的最大值
while(hh <= tt && a[q[tt]] >= a[i]) tt--;
q[++ tt] = i;
}
例题--滑动区间
题目
求区间中的最大和最小值,分两行输出
🐴
#include<iostream>
using namespace std;
const int N = 1000010;
int a[N],q[N];
int n,k;
int hh = 0,tt = -1;
int main(){
cin >> n >> k;
for(int i = 0;i < n;i ++) scanf("%d",&a[i]);
//遍历要处理的数据
for(int i = 0;i < n;i ++){
//队头滑出区间
if(hh <= tt && q[hh] <i - k + 1) hh ++; //该题保证一次一个滑出,所以可以用if
//保证入队的成为当前队列的最大值
while(hh <= tt && a[q[tt]] >= a[i]) tt--;
q[++ tt] = i;
if(i >= k - 1) printf("%d ",a[q[hh]]);
}
cout << endl;
hh = 0,tt = -1;
for(int i = 0;i < n;i ++){
if(hh <= tt && q[hh] < i - k + 1) hh ++;
while(hh <= tt && a[q[tt]] <= a[i]) tt --;
q[++ tt] = i;
if(i >= k - 1) printf("%d ",a[q[hh]]);
}
return 0;
}