单调队列——POJ - 2823
题目含义
给出一个区间的长度,要你在一堆数中移动这个区间(保持区间长度不变),找出对应的最大最小值
题目解析
这个区间在向右移动,那么时时刻刻有数离开这个区间,有数加入这个区间,这样的话可以考虑单调队列
把这些数按从大到小的顺序放入一个数组,并且从大到小判断这个数是否满足在这个区间,不满足就取出
这样队列头就是这个区间的最大值,同理最小
题目代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e6+7;
int n,k,h,t;
int a[maxn],q[maxn],maxx[maxn],minn[maxn];
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
h=1,t=0;
for(int i=1;i<=n;i++){
while(h<=t&&a[q[t]]<=a[i])t--;///满足单调数组单调递减的性质
q[++t]=i;
while(i-k>=q[h])h++;///判断此时的最大值a[q[h]]的下标在不在区间内
maxx[i]=a[q[h]];
}
h=1,t=0;
for(int i=1;i<=n;i++){
while(h<=t&&a[q[t]]>=a[i])t--;///单调递增的数组
q[++t]=i;
while(i-k>=q[h])h++;
minn[i]=a[q[h]];
}
if(k>=n){
printf("%d\n%d\n",minn[n],maxx[n]);
}
else{
for(int Qi=k;i<n;i++)
printf("%d ",minn[i]);
printf("%d\n",minn[n]);
for(int i=k;i<n;i++)
printf("%d ",maxx[i]);
printf("%d\n",maxx[n]);
}
return 0;
}
挺简单的,本来以为能一次过的,结果又忘了算完最大值后要重置h和t

浙公网安备 33010602011771号