hdu~3530(單調佇列)
阿新 • • 發佈:2019-02-14
單調佇列就是佇列中的元素是單調遞增或遞減的。比如把 5 2 3 1 4 入隊:
減:、、、、、、、、、、、增:
5 、、、、、、、、、、、、5
5 2 、、、、、、、、、、、2
5 3 、、、、、、、、、、、2 3
5 3 1、、、、、、、、 、、1
5 4 、、、、、、、、、、、1 4
這個還是好理解的,但是,我們得會用單調佇列這一特性去解決題目,抽象出題目中有類似的操作。
題意:
給三個數 n,x,y;
接下來n個數num[1~n];
求滿足這個條件的最長區間長度:區間內最大值與最小值之差在 x~y之間。
方法:
單調佇列記錄下標。
由一個遞增,一個遞減的單調佇列,可得前面的某個位置~當前位置 的最大差值def=num[q1.front()]-num[q2.front()];
如果def>y,則讓下標靠前的那個出佇列。
上程式碼,看註釋:
#include <stdio.h> #include <iostream> #include <deque> using namespace std; inline int fmax(int a,int b){return a>b?a:b;} int main() { int n,x,y; int num[100005]; while(scanf("%d %d %d",&n,&x,&y)!=EOF) { for(int i=1;i<=n;++i) scanf("%d",&num[i]); deque<int >q1,q2; //兩個佇列,q1.front()存最大值,q2.front()存最小值 int max=0,last=0; //last記錄最後彈出元素的位置 for(int i=1;i<=n;i++){ while(!q1.empty() && num[i]>num[q1.back()]) q1.pop_back();//維護佇列單調型 while(!q2.empty() && num[i]<num[q2.back()]) q2.pop_back(); q1.push_back(i); q2.push_back(i); //若對不空,且def>y,讓下標靠前的出隊。 while(!q1.empty() && !q2.empty() && num[q1.front()]-num[q2.front()]>y){ if(q1.front()>q2.front()) { last=q2.front(); q2.pop_front(); } else if(q1.front()<q2.front()) { last=q1.front(); q1.pop_front(); } else if(q1.front()>q2.front()) { last=q2.front(); q1.pop_front(); q2.pop_front(); } } if(!q1.empty() && !q1.empty() && num[q1.front()]-num[q2.front()]>=x) max=fmax(max,i-last);//若當前區間的def滿足>=x,取區間最大長度 } printf("%d\n",max); } return 0; }