题意

给定 和数组 。求 中的最大值和最小值

分析

这题要用到单调队列。
什么是单调队列?顾名思义,就是里面元素是单调的队列。
假如我们有这么一个队列,里面的元素都是合法且单调的。那么最大值和最小值不是呼之欲出了吗?
那么现在如何维护队列单调呢?
以求最大值为例。
假如当前维护了一个队列。现在新插入一个元素,这个元素如果比上一个元素大,那么上一个元素一定不会作为答案出现在之后的滑动窗口中,因为这个元素不仅在上一个元素的后面,而且还比它大。于是,上一个元素可以滚蛋了!然后再比较它和上上个元素,一直比较下去。比较完,我们得到了就是一个单调减的队列,里面的元素都无法再删去了!那么最大值就是队首的值。
做完了吗?
还没有!滑动窗口的大小是有限制的,也就是说,当目前的 和队首的距离超过 ,我们就要跟队首说拜拜了。队首要加一。这样子,我们就成功维护了一个长度为 且单调减的队列,最大值在队首。
求最小值的过程和最大值几乎一模一样。

代码如下

#include <bits/stdc++.h>
#define N 1000005
using namespace std;
int read(){
    int x, f = 1;
    char ch;
    while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
    x = ch - '0';
    while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
    return x * f;
}
int q[N], a[N], x = 1, y;
int main(){
    int i, j, n, m;
    n = read(); m = read();
    for(i = 1; i <= n; i++) a[i] = read();
    for(i = 1; i <= n; i++){
        q[++y] = i;
        while(x < y && a[q[y]] <= a[q[y - 1]]) q[y - 1] = q[y], y--;
        while(x <= y && i - q[x] + 1 > m) x++;
        if(i >= m) printf("%d ", a[q[x]]);
    }
    printf("\n");
    x = 1, y = 0;
    for(i = 1; i <= n; i++){
        q[++y] = i;
        while(x < y && a[q[y]] >= a[q[y - 1]]) q[y - 1] = q[y], y--;
        while(x <= y && i - q[x] + 1 > m) x++;
        if(i >= m) printf("%d ", a[q[x]]);
    }
    return 0;
}