维护一个单调队列,以最小值为例,队首是最小值的下标,将新加入的元素加入到队尾,但要pop掉那些比新加入元素还要大的元素再加入队尾(即如果比队首最小值还要小将整个队列pop掉再加入队尾),但是队首元素不一定就是这个窗口的答案,它可能在窗口的左边,所以从队首开始pop掉那些下标比i-m还要小的元素,最大值同理;

#include <cstdio>
#include <queue>
using namespace std;
const int N = 1e6+10;
int n,m,a[N];
void mi_deque(){
    deque<int> q;
    for(int i = 0;i < n;i++){
        while(!q.empty()&&a[q.back()] > a[i]){
            q.pop_back();
        }
        q.push_back(i);
        while(!q.empty()&&q.front() <= i-m){
            q.pop_front();
        }
        if(i >= m-1){
            printf("%d ",a[q.front()]);
        }
    }
    puts("");
}
void mx_deque(){
    deque<int> q;
    for(int i = 0;i < n;i++){
        while(!q.empty()&&a[q.back()] < a[i]){
            q.pop_back();
        }
        q.push_back(i);
        while(!q.empty()&&q.front() <= i-m){
            q.pop_front();
        }
        if(i >= m-1){
            printf("%d ",a[q.front()]);
        }
    }
    puts("");
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 0;i < n;i++) scanf("%d",a+i);
    mi_deque();
    mx_deque();
    return 0;
}