HDU 3530 Subsequence(单调队列)

题目链接:Click here~~

题意:

给一个长度为 n 的序列,找出最长的子序列满足 子序列中的最大值和最小值 的差在区间 [m,k] 范围内。

解题思路:

维护两个单调队列,分别存最小值和最大值。

利用 two pointer 的思想,用 j 指向正在考虑中的区间左端点位置,出队时不断右移左指针 j,对于每个 i 不断更新 ans。

Ps.也可以根据贪心的思想,出队时每次删除较小的位置,但需要不断维护两个队列中的最小位置,写法没 two pointer 优美。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 1e5 + 5;

int a[N],qmin[N],qmax[N];

int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        int head1 = 0 , rear1 = -1;
        int head2 = 0 , rear2 = -1;
        int ans = 0;
        for(int i=0,j=0;i<n;i++)
        {
            while(head1 <= rear1 && a[ qmin[rear1] ] >= a[i])
                rear1--;
            qmin[++rear1] = i;

            while(head2 <= rear2 && a[ qmax[rear2] ] <= a[i])
                rear2--;
            qmax[++rear2] = i;

            while(a[ qmax[head2] ] - a[ qmin[head1] ] > k)
            {
                if(j == qmin[head1])
                    ++head1;
                if(j == qmax[head2])
                    ++head2;
                j++;
            }

            if(j <= i && a[ qmax[head2] ] - a[ qmin[head1] ] >= m)
                ans = max(ans,i-j+1);
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(HDU 3530 Subsequence(单调队列))