单调队列是指:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。
单调队列顾名思义就是一个有规律的队列,这个队列的规律是:所有在队列里的数都必须按递增(或递减)的顺序列队。
例如:
有如下一串数字:1 5 3 4 2
首先第一个数字1先进队列,que = {1};
之后第二个数字5大于1,则1出队列5进队列,que = {5};
下一步第三个数字3小于5,进队列,que = {5,3};
下一步第四个数字4大于3,则3出队列4进队列,que = {5,4};
下一步第五个数字2小于4,进队列,que = {5,4,2};
这样最后队列里的数字为单调递减排列。
模板:
//que数组存储数据在a数组中的下标
que[++tail] = 1;//第一个数据先进入队列
for(int i = 2; i <= n; i++){
while(head <= tail && i - que[head] == k)//判断最大的数是否在范围之内,若不在则出队列
head++;
while(head <= tail && a[i] >= a[que[tail]])//当新插入的数比队尾大时,弹出队尾的数
tail--;
que[++tail] = i; //新插入的数进入队列
if(i >= k)
printf("%d\n", a[que[head]]);
}
例题:
#include<stdio.h>
#define maxn 2000001
int head = 1, tail = 0;
int a[maxn], que[maxn];
int main(){
int n, k;
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
//单调队列递减,则队头为最大元素
que[++tail] = 1;
for(int i = 2; i <= n; i++){
while(head <= tail && i - que[head] == k)//判断最大的数是否在范围之内,若不在则出队列
head++;
while(head <= tail && a[i] >= a[que[tail]])//当新插入的数比队尾大时,弹出队尾的数
tail--;
que[++tail] = i; //新插入的数进入队列
if(i >= k)
printf("%d\n", a[que[head]]);
}
return 0;
}