AcWing 154. 滑动窗口(单调队列板子)

以求最大值为例
使用单调队列储存当前窗口内单调递减的元素的下标,队首代表窗口内的最大值元素,队尾代表窗口内的尾元素
也就是说该单调队列代表滑动窗口内的一个从最大值元素到尾元素降序子序列
队列中需要存放窗口元素的下标值,便于判断队首是否需要出队(下面会解释)
一.队列维护过程:
当窗口发生滑动时:先操作队首,再操作队尾
Ⅰ队首:
只有当 队首的元素(窗口在未滑动之前的最大值)从窗口滑出时,队首进行出队操作pop_front
Ⅱ队尾:
当新元素滑入窗口时,需要把新元素插入队尾,将会有两种情况
1:直接插入:
当新元素小于队尾时(自然也小于队列中所有元素),它可能在将来的某个时候成为队首成为窗口的最大值,此时进行入队操作push_back
2:先删后插:
当新元素大于等于队尾时,此时原队尾永远不可能成为最大值,被舍弃删除,进行原队尾出队操作pop_back
重复此操作直到新元素小于队尾或者队列为空(说明新元素是窗口滑动后的最大值自然就把原队列删完了)
最后进行新元素入队push_back
这样经过一轮维护后得到的队列就是一个单调递减的队列,队首代表当前窗口的最大值
二.样例模拟:
数组:1 3 -1 -3 5 3 6 7
1:1 3 -1 -3 5 3 6 7
当前队列为空,1入队
操作后队列为:1
2:1 3 -1 -3 5 3 6 7
3!<1,1出队
队列空,3入队
操作后队列为:3
3:1 3 -1 -3 5 3 6 7
-1<3,-1入队
操作后队列为:3 -1
4:1 3 -1 -3 5 3 6 7
队首未滑出
新元素-3<-1,-3入队
操作后队列为:3 -1 -3
5:1 3 -1 -3 5 3 6 7
队首滑出,3出队
新元素5!<-3,-3出队
新元素5!<-1,-1出队
队列空,5入队
操作后队列:5
6:1 3 -1 -3 5 3 6 7
队首未滑出
新元素3<5,3入队
操作后队列:5 3
7:1 3 -1 -3 5 3 6 7
队首未滑出
新元素6!<3,3出队
新元素6!<5,5出队
队列空,6入队
操作后队列:6
8:1 3 -1 -3 5 3 6 7
队首未滑出
新元素7!<6,6出队
队列空,7入队
操作后队列:7
得出答案:3 3 5 5 6 7
三.代码:
如何判断队首元素是否从窗口中滑出?
如果用数组中元素的值,不易判断
如果队列中储存的是数组元素的下标,可以通过窗口循环变量i和队首所代表的下标作差,看是否超过窗口长度
窗口最右端下标:循环变量i
窗口最左端下标:i-len+1