队列就是一排数,那么显而易见,单调队列就是元素之间呈单调关系,可以是单调递增的关系,也可以是单调递减的关系,而且队首与队尾都可以进行出队操作,而只有队尾可以进行入队操作。
常用操作:
1. 插入:若新元素插入队尾会破坏队列的单调性,就删除队尾元素,直到插入后不破坏队列的单调性。
2. 获取最优值: 若需要得到最大,最小值,一般可以通过直接访问队首与队尾的元素得到。
操作流程:
如一个队列:(1,3,2,1,5,6)
得到单调队列的过程:
首先第一个元素,1入队:得到1
再得到第二个元素,3入队: 得到1,3
2入队,但因为2小于3,所以3弹出,得到:1,2
1入队,又因为1小于2,所以3弹出,得到:1,1
5入队,得到:1,1,5
6入队,得到:1,1,5,6
所以1,1,5,6就是最终的单调队列
这就是队列的实现原理,以通俗易懂的方式呈现出来。
最后列道题帮助记忆:
给定一个长度为n的数列,求长度为k的定长连续子区间{a1,a2,a3,a4,…,ak-1,ak}{a2,a3,…,ak,ak+1}……中每个区间的最大值和最小值。
代码:
#include <cstdio>
#include <cstring>
#include<iostream>
#define MAXN 80050
#define LL long long
using namespace std;
LL q[MAXN];
int main()
{
int n;
scanf("%d",&n);
LL a;
LL ans=0;
int rear=-1,front=0;
for(int i=0;i<n;i++){
scanf("%I64d",&a);
while(rear>=front&&q[rear]<=a)rear--; //看最后一位数与下一位入队的数谁大,直到新入队的数比前一位大为止,这是队列的核心代码。
q[++rear]=a; //将数放入队列
ans+=rear; //记录下长度
}
cout<<ans<<endl;
return 0;
}