题意 有一个n长的序列,用k长的窗口在上面滑动,去每次窗口中最小和最大的数。
思路 使用单调队列,维护这个队列是单调的。以取最小元素为例,若窗口内左边元素>=右边元素,则左边元素失去保留的意义,删除它。因此我们的单调队列是始终递增的。用STL的deque实现单调队列。
#include <queue>
#include <cstdio>
#include <iostream>
#include <map>
using namespace std;
const int maxn = 1000006;
#define mp make_pair
#define fi first
#define se second
typedef bool (*PF)(int x,int y);
typedef pair<int,int> pii;
int a[maxn];
int n,k;
deque<pii> dq;
bool cmp1(int x,int y){
return x>y;
}
bool cmp2(int x,int y){
return x<y;
}
void find(PF cmp){
dq.clear();
for(int i=0;i<k-1;i++){
while(dq.size()>0 && cmp(dq.back().fi,a[i])==1){
dq.pop_back();
}
dq.push_back(mp(a[i],i));
}
for(int i=k-1;i<n;i++){
while(dq.size()>0 && cmp(a[i],dq.back().fi)==0){
dq.pop_back();
}
dq.push_back(mp(a[i],i));
if(i < n-1)
printf("%d ",dq.front().fi);
else
printf("%d\n",dq.front().fi);
if(dq.front().se == i-k+1)
dq.pop_front();
}
}
int main(){
scanf("%d%d",&n,&k);
if(k>n)
return 0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
find(cmp1);
find(cmp2);
return 0;
}