HDU 3530 Subsequence(单调队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3530

题意:给定一个长度为n的数列。求一个尽可能长的子列[L,R],使得该子列之内的最大最小值之差x满足M<=x<=K?

思路:用一个单调队列保存最大的(队列中的元素递减),用一个单调队列保存最小的(队列中的元素递增),这样每次取队头元素作差就是x的值,当x大于K时,使得队头元素较小的一个前移。最后总能使得x<=K。此时判断x是否大于等于M,满足则更新答案.





const int MAX=100005;

int Q1[MAX],head1,tail1;

int Q2[MAX],head2,tail2;

int a[MAX],n,M,K;



int main()

{

    while(scanf("%d%d%d",&n,&M,&K)!=-1)

    {

        int i;

        for(i=1;i<=n;i++) scanf("%d",&a[i]);

        int ans=0;

        head1=tail1=0;

        head2=tail2=0;

        for(i=1;i<=n;i++)

        {

            while(head1<tail1&&a[i]>=a[Q1[tail1-1]]) tail1--;

            Q1[tail1++]=i;

            while(head2<tail2&&a[i]<=a[Q2[tail2-1]]) tail2--;

            Q2[tail2++]=i;

            while(a[Q1[head1]]-a[Q2[head2]]>K)

            {

                if(Q1[head1]<Q2[head2]) head1++;

                else head2++;

            }

            if(a[Q1[head1]]-a[Q2[head2]]>=M)

            {

                if(head1==0&&head2==0) ans=max(ans,i);

                else if(head1==0) ans=max(ans,i-Q2[head2-1]);

                else if(head2==0) ans=max(ans,i-Q1[head1-1]);

                else ans=max(ans,i-max(Q1[head1-1],Q2[head2-1]));

            }

        }

        printf("%d\n",ans);

    }

    return 0;

}

 

 

你可能感兴趣的:(sequence)