单调队列
滑动窗口最值:队头永远是窗口里的最大值,每个元素进出各一次 → O(n)。
一、互动演示:滑动窗口最大值
数组 [1,3,-1,-3,5,3],窗口 k=3。蓝色=当前窗口,下方是单调队列(存下标,值递减),绿色=队头=当前最大值。
↓ 单调队列(值从队头到队尾递减)
点“下一步”,逐个把元素加入窗口。
二、参考代码(洛谷 P1886)
int head = 1, tail = 0; // q 存下标
for (int i = 1; i <= n; i++) {
while (head <= tail && a[q[tail]] <= a[i]) tail--; // 弹掉队尾更小的
q[++tail] = i; // 入队尾
while (q[head] <= i - k) head++; // 队头滑出窗口
if (i >= k) cout << a[q[head]] << " "; // 队头=最大值
}
求最小值把 <= 改成 >=。信号:滑动窗口最值、可滑动窗口的 DP 转移优化。