单调队列——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