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;
}
人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
原文地址:https://www.cnblogs.com/kuangbin/p/3066034.html