hdu3530单调队列(双)
先前接触了单调队列的题,确实是很重要的知识点,单调队列不难,就是用栈或队列来通过对队头的判断来实现队列保持单调。
题意:
给出一个大小为n的数组a[n];
求其中最大值减最小值在【m,k】中的字串最长长度。
思路:
用两个单调队列分别维护a【i】前元素中的最大值与最小值的下标,top为最值。
然后当最值之差过大时,a【i】的满足题意的最长字串为最最后操作last与【i】的距离 其中last取离i最远的一个
这样就出来了,单调队列主要是在于数组操作上,要将数组各种变量与题意紧紧联系起来。。。
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; inline int max(int a ,int b){return a>b?a:b;} const int N = 100010; int s1[N],s2[N]; int a[N]; int main() { int n,m,k,top1,top2,last1,last2,tail1,tail2,ans; while(scanf("%d%d%d",&n,&m,&k)!=EOF) { for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); top1=0;top2=0;tail1=0;tail2=0;ans=0;last1=0;last2=0; for(int i=1;i<=n;i++) { //max while(top1<tail1&&a[s1[tail1-1]]<=a[i])tail1--; //top1最大元素 s1[tail1++]=i; //min while(top2<tail2&&a[s2[tail2-1]]>=a[i])tail2--; //top2最小元素 s2[tail2++]=i; while(a[s1[top1]]-a[s2[top2]]>k) { if(s1[top1]<s2[top2]) last1=s1[top1++]; else last2=s2[top2++]; } if(a[s1[top1]]-a[s2[top2]]>=m) { ans=max(ans,i-max(last1,last2)); } } cout<<ans<<endl; } return 0; }