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;
}


 

原文地址:https://www.cnblogs.com/amourjun/p/5134170.html