3月30日每日一题 : https://ac.nowcoder.com/discuss/394776

Solution

滑动窗口最值问题,就是单调队列的模板题。

先讲一下个人对单调队列的理解:
举个维护区间最小值的例子,
主要就是用 head 和 tail 双指针来对队列里的元素进行维护,
当 q[head]+m<=i 说明队首元素已经跟不上滑动窗口,所以移动 head 指针,
当 a[ q[tail] ]>a[i] 说明队尾元素比当前元素大,失去优先级,移动尾指针,
这样的话,那么 q[head] 就是窗口中最小元素的索引了。

for(int i=1;i<=n;i++){
    while(head<=tail&&q[head]+m<=i) ++head;
    while(head<=tail&&a[q[tail]]>a[i]) --tail;
    q[++tail]=i;
}

Code

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define eps 1e-8
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}
const ull base=2333; const ull pp=19260811; const ull ppp=999998639;

const int manx=1e6+5;
const int mo=998244353;

ll q[manx],a[manx];

int main(){
    ll n=read(),k=read();
    for(int i=1;i<=n;i++) a[i]=read();
    ll head=1,tail=0;
    for(int i=1;i<=n;i++){
        while(head<=tail&&q[head]+k<=i) ++head;
        while(head<=tail&&a[q[tail]]>a[i]) --tail;
        q[++tail]=i;
        if(i>=k) printf("%lld ",a[q[head]]);
    }
    printf("\n");
    head=1,tail=0;
    for(int i=1;i<=n;i++){
        while(head<=tail&&q[head]+k<=i) ++head;
        while(head<=tail&&a[q[tail]]<a[i]) --tail;
        q[++tail]=i;
        if(i>=k) printf("%lld ",a[q[head]]);
    }
    return 0;
}