HDU 3530 Subsequence(单调队列)

Subsequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3266    Accepted Submission(s): 1063


Problem Description
There is a sequence of integers. Your task is to find the longest subsequence that satisfies the following condition: the difference between the maximum element and the minimum element of the subsequence is no smaller than m and no larger than k.
 

 

Input
There are multiple test cases.
For each test case, the first line has three integers, n, m and k. n is the length of the sequence and is in the range [1, 100000]. m and k are in the range [0, 1000000]. The second line has n integers, which are all in the range [0, 1000000].
Proceed to the end of file.
 

 

Output
For each test case, print the length of the subsequence on a single line.
 

 

Sample Input
5 0 0 1 1 1 1 1 5 0 3 1 2 3 4 5
 

 

Sample Output
5 4
 

 

Source
 

 

Recommend
zhengfeng
 

 

 

 

 

很简单的单调队列的题目;

 

 

今天做的时候,一直以为可以二分答案做。

结果坑了一天,晚上适牛告诉我二分是不对的。

比如n=5  m=k=3

1 2 3 4 10000

二分的时候长度为2挂掉。结果就错了。正确答案应该是4

 

只有通过单调队列扫一遍。

维护一个最大值和一个最小值。

保证最大值-最小值时满足上界条件的。

然后如果下界条件满足就更新答案。

 

//============================================================================

// Name        : HDU.cpp

// Author      : 

// Version     :

// Copyright   : Your copyright notice

// Description : Hello World in C++, Ansi-style

//============================================================================



#include <iostream>

#include <string.h>

#include <stdio.h>

#include <algorithm>

using namespace std;

const int MAXN=100010;

int a[MAXN];

int q1[MAXN],q2[MAXN];//q1是维护最大值,q2维护最小值

int n,m,k;





int main()

{

//    freopen("in.txt","r",stdin);

//    freopen("out.txt","w",stdout);

    while(scanf("%d%d%d",&n,&m,&k)==3)

    {

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

            scanf("%d",&a[i]);

        int ans=0;

        int rear1,front1,rear2,front2;

        rear1=front1=0;

        rear2=front2=0;

        int now=0;

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

        {

            while(front1<rear1 && a[q1[rear1-1]]<a[i])rear1--;

            q1[rear1++]=i;

            while(front2<rear2 && a[q2[rear2-1]]>a[i])rear2--;

            q2[rear2++]=i;

            while(front1<rear1 && front2<rear2 && a[q1[front1]]-a[q2[front2]]>k)

            {

                if(q1[front1]<q2[front2])

                {

                    now=q1[front1];

                    front1++;

                }

                else

                {

                    now=q2[front2];

                    front2++;

                }

            }

            if(front1<rear1 && front2<rear2 && a[q1[front1]]-a[q2[front2]]>=m)

                ans=max(ans,i-now);

        }

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

    }

    return 0;

}

 

 

 

 

 

你可能感兴趣的:(sequence)