题意:
原题来自:POJ 2823
给一个长度为 NN 的数组,一个长为 KK 的滑动窗体从最左端移至最右端,你只能看到窗口中的 KK 个数,每次窗体向右移动一位。
你的任务是找出窗体在各个位置时的最大值和最小值。
思路:
滑动窗口的模板题:对于取最小值:首先比较进队元素与队尾,如果比队尾小,说明队尾不会是这个区间的最小值,可以将队尾出列,然后再和新队尾比较;然后将进队元素进队。之后再比较是否容器内有超出长度,将队头和当先所在的点的下标进行比较,将超出的队头出列,这里使用的是deque,是一种双开头的队列,可以对队头和队尾都进行如上操作,当然也可以用数组加双指针进行模拟,原理是一样的,最后在长度大于设定的窗口长度是输出队头。取最大值同理。
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <deque>
#define ll long long
using namespace std;
int n,m;
deque<int> q1,q2;//q1最小,q2最大值
int a[1000005];
int maxn=-1e9;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];:
while(!q1.empty()&&a[i]<a[q1.back()]) q1.pop_back();
q1.push_back(i);
while(!q1.empty()&&q1.front()<i-m+1) q1.pop_front();
if(i>=m){
cout<<a[q1.front()]<<" ";
}
}
cout<<endl;
for(int i=1;i<=n;i++){
while(!q2.empty()&&a[i]>a[q2.back()]) q2.pop_back();
q2.push_back(i);
while(!q2.empty()&&q2.front()<i-m+1) q2.pop_front();
if(i>=m){
cout<<a[q2.front()]<<" ";
}
}
return 0;
}