前言
其实单调队列不是真正意义上的队列,它只是一个存在于你脑海里的一个虚拟的队列,虚拟地进行队列的操作。。。(好玄学~~)
0.单调队列思想
单调队列,正如其名,是一个单调的队列,单调递增或者单调递减,所以队首永远是最小值或最大值,这就是单调队列的用处——求一段区间里的最大值或最小值。
1.单调队列操作
通常我们用一个a[]数组存原数组,用一个q[]数组表示单调队列,这个q[]数组存的是队列里元素在原数组里的位置标号(下标)。单调队列与别的队列的原理不太一样,它是在队尾插入元素,在两头删除元素。
下面以一个单调递增队列为例:
入队操作
将要放入队尾的元素e与队尾元素t进行比较,如果e<t,则将t踢出队列,继续拿e与队尾元素比较,直到找到一个元素k<e,把e放在k的后面,至于那些被踢掉的元素。。。就不要了。
出队操作
因为单调队列是要求区间的最小值,所以前面的元素总会有没用的时候,这个时候就要把那些被顶出区间的元素踢掉。
2.单调队列裸题
讲了这么多感觉还是很玄学,那就拿例题来解释吧~~
【题目链接】
洛谷【1440】
【题目描述】
一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值。若前面的数不足m项则从第1个数开始,若前面没有数则输出0。
【输入格式】
第一行两个数n,m。
第二行,n个正整数,为所给定的数列。
【输出格式】
n行,第i行的一个数ai,为所求序列中第i个数前m个数的最小值。
【输入样例】
6 2
7 8 1 4 3 2
【输出样例】
0
7
7
1
1
3
【说明】
数据范围:m≤n≤2000000
【题解】
多么裸的单调队列~~
弄一个单调递增的单调队列,每次输出队首元素a[q[head]]。
有一点要注意的:“所求序列中第i个数前m个数的最小值”.(第一次被坑了)
【程序】