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;
} 
京公网安备 11010502036488号