单调队列
一、概念
单调队列是指:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。
单调队列顾名思义就是一个有规律的队列,这个队列的规律是:所有在队列里的数都必须按递增(或递减)的顺序列队。
例如:
有如下一串数字: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]]);
}
三、例题:
题目描述
有一个 1 x n 的矩阵,有n个整数。
现在给你一个可以盖住连续k个数的木板。
一开始木板盖住了矩阵的第i~k 个数,每次将木板向右移动一个单位,直到右端与第n个数重合。
每次移动前输出被覆盖住的数字中最大的数是多少。
输入格式
第一行两个整数n,k,表示共有 n 个数,木板可以盖住 k 个数。
第二行n个整数,表示矩阵中的元素。
输出格式
共 n - k + 1行,每行一个整数。
第i行表示第 i ~i + k - 1个数中最大值是多少。
样例输入
5 3
1 5 3 4 2
样例输出
5 5 4
AC代码;
#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(inti = 1; i <= n; i++){
scanf("%d",&a[i]);
}
//单调队列递减,则队头为最大元素
que[++tail]= 1;
for(inti = 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]]);
}
return0;
}