题目链接:http://poj.org/problem?id=2823
题目大意:给出一组数,一个固定大小的窗体在这个数组上滑动,要求出每次滑动该窗体内的最大值和最小值。
这就是典型的单调队列,单调队列的作用就在此。单调队列的队首为区间内的最值,可是整个队列不用保持单调。
用两个队列分别处理最大值和最小值,在此说明一下最大值;
往队列中加入值num时,从队尾開始扫,直到遇到一个小于num的d值,将num插入d的后一位。之后的元素所有无效化(无论后面的元素即可)。查找最大值的时候,从队首開始找,假设该元素没在此时的区间的话,查找下一个,直到找到满足条件的第一个元素,这个元素便是最值。
求最小值和最大值大同小异,仅仅须要将加入值num的条件改一下就可以。
代码例如以下:
#include <iostream> #include <cstdio> #define N 1000001 using namespace std; struct que { int i,x; }q1[N],q2[N];//队列 int a[N];//输入数据 int n,k; int head,tail;//分别代表队首和队尾的下标,head之前和tail之后的元素都无效 void getmax() { head=1;tail=0; for(int i=0;i<n;i++) { while(head<=tail&&q1[tail].x<a[i]) //检測从队尾開始扫,直到遇到一个小于num的d值 tail--; tail++; //将num插入d的后一位。</span> q1[tail].x=a[i]; q1[tail].i=i; if(i>=k-1) { while(q1[head].i<=i-k) head++; if(i!=n-1) printf("%d ",q1[head].x); else printf("%d\n",q1[head].x); } } } void getmin() { head=1;tail=0; for(int i=0;i<n;i++) { while(head<=tail&&q2[tail].x>a[i]) tail--; tail++; q2[tail].x=a[i]; q2[tail].i=i; if(i>=k-1) { while(q2[head].i<=i-k) head++; if(i!=n-1) printf("%d ",q2[head].x); else printf("%d\n",q2[head].x); } } } int main() { while(~scanf("%d%d",&n,&k)) { for(int i=0;i<n;i++) scanf("%d",&a[i]); getmin(); getmax(); } return 0; }