Solution

单调队列模板题。

具体思想:从前到后遍历序列,维护一个队列,使队列的队首一直是窗口中的最值。以最小值为例,若序列当前位置的数比队列中的队尾小,那就意味着当前位置的数贡献更大,即更有可能成为之后的最小值,于是就可以弹出队尾元素将新元素插入。注意及时从队首排除不符合范围的元素。

由于每个数至多进队列一次,出队列一次,所以时间复杂度为

Code

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1e6+10;
int n,k,a[maxn],q[maxn][2],hd,tl;
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++){
        while(hd<=tl&&a[i]<q[tl][0])
            tl--;
        q[++tl][0]=a[i],q[tl][1]=i;
        if(q[hd][1]<=i-k)
            hd++;
        if(i>=k)
            cout<<q[hd][0]<<" ";
    }
    cout<<endl;
    hd=tl=0;
    for(int i=1;i<=n;i++){
        while(hd<=tl&&a[i]>q[tl][0])
            tl--;
        q[++tl][0]=a[i],q[tl][1]=i;
        if(q[hd][1]<=i-k)
            hd++;
        if(i>=k)
            cout<<q[hd][0]<<" ";
    }
    return 0;
}