题意:n个数,求每连续k个数中的最大最小值。
思路:单调队列模板题。。以最大数为例,开一个队列,每个数按顺序入队,需要保证队列单调递减,如果入队时前面比当前的数大,就让前面的出队。如果队首到队尾的元素位置差超过k,就让队首出队。
为什么可以这样做呢,因为“窗口”的大小是k,晚来的一定晚走,如果晚来的比先来的大,那么先来的就没有存在的意义了;如果晚来的比先来的小,当先来的走了之后,晚来的有可能成为最大的。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
using namespace std;
const int maxn=1e6+10;
struct node{
int pos;
int val;
node(int p,int v):pos(p),val(v){}
node(){}
};
node minque[maxn];
node maxque[maxn];
int minans[maxn];
int maxans[maxn];
int minhead,mintail;
int maxhead,maxtail;
void init(){
minhead=mintail=0;
maxhead=maxtail=0;
}
int main(){
int n,k;
while(cin>>n>>k){
int a;
for(int i=0;i<k;i++){
scanf("%d",&a);
while(mintail!=minhead&&a<=minque[mintail-1].val)mintail--;
minque[mintail++]=node(i,a);
while(maxtail!=maxhead&&a>=maxque[maxtail-1].val)maxtail--;
maxque[maxtail++]=node(i,a);
}
//
for(int i=k;i<=n;i++){
while(i-minque[minhead].pos>k)minhead++;
while(i-maxque[maxhead].pos>k)maxhead++;
minans[i]=minque[minhead].val;
maxans[i]=maxque[maxhead].val;
if(i==n)break;
scanf("%d",&a);
while(a<=minque[mintail-1].val&&mintail!=minhead)mintail--;
minque[mintail++]=node(i,a);
while(a>=maxque[maxtail-1].val&&maxtail!=maxhead)maxtail--;
maxque[maxtail++]=node(i,a);
}
for(int i=k;i<=n;i++){
printf("%d",minans[i]);
i==n?printf("\n"):printf(" ");
}
for(int i=k;i<=n;i++){
printf("%d",maxans[i]);
i==n?printf("\n"):printf(" ");
}
}
return 0;
}