標籤:acm c++ poj 資料結構 隊列
題目連結:http://poj.org/problem?id=2823
題目大意:給出一組數,一個固定大小的視窗在這個數組上滑動,要求出每次滑動該視窗內的最大值和最小值。
這就是典型的單調隊列,單調隊列的作用就在此。單調隊列的隊首為區間內的最值,但是整個隊列不用保持單調。
用兩個隊列分別處理最大值和最小值,在此說明一下最大值;
往隊列中添加值num時,從隊尾開始掃,直到遇到一個小於num的d值,將num插入d的後一位。之後的元素全部無效化(不管後面的元素就行)。尋找最大值的時候,從隊首開始找,如果該元素沒在此時的區間的話,尋找下一個,直到找到滿足條件的第一個元素,這個元素便是最值。
求最小值和最大值大同小異,只需要將添加值num的條件改一下即可。
代碼如下:
#include <iostream>#include <cstdio>#define N 1000001using 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;}