单调队列(经典问题:滑动窗口最大值)
- 和单调栈类似的数据结构
- 经典问题:滑动窗口最大值:给出一个可能包含重复的整数数组,和一个大小为 k 的滑动窗口, 从左到右在数组中滑动这个窗口,找到数组中每个窗口内的最大值。
- 单调队列中的元素是严格单调的。我们在求解这个问题的时候需要维护他的单调性。
- 队首元素即为当前位置的最大值。假设要求滑动窗口中的最大值。我们就需要确保滑动窗口中的元素从队首到队尾是递减的。
- 每滑动一次就判断当前元素和队尾元素的关系,如果放入队尾满足单调递减,那么放入即可;如果放入不满足,就需要删除队尾元素直到放入当前元素之后满足队列单调递减。同时要确保已经出窗口的最大值(队首元素)被删除掉。
- 设单调队列中的元素用<>表示
思路
-
(关键)划分解空间:令DP[i][k]DP[i][k]DP[i][k],以第i个段为结尾,且第i个段取值为k时候的不下降的连续天数(以第i个段为结尾)
-
状态转移:
DP[i][j]=maxk≤jDP[i−1][k]+1DP[i][j] = max_{k \leq j} DP[i-1][k] + 1DP[i][j]=maxk≤jDP[i−1][k]+1
如果不存在这样的k那么取值为0。显然k取能够取得最大值即可。 -
随着j的提升,DP[i][j]DP[i][j]DP[i][j]是单调不减的(由定义很容易看到)
-
状态转移(如图所示):
-
对于每个i值,使用类似双端队列或单调队列的方式维护段的取值即可。
- 加1可使用一个全局标记,代表该队列中所有的值都已经被加上某个数字