GESP8 · 提高

单调队列

滑动窗口最值:队头永远是窗口里的最大值,每个元素进出各一次 → 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 转移优化。