hdu3530 Subsequence 单调队列

Subsequence

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


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   |   We have carefully selected several similar problems for you:   3535  3529  3528  3527  3531 
 


题意:求一个最长子序列,序列最大值与最小值的差d, m<=d<=k。

思路:用两个单调队列维护最大值、最小值,从左往右扫一遍。当队首元素差大于k,删除队首元素,我们需要删除的应该是两个队首元素数组下标小的那个。我们这样考虑,假设当前扫到i,答案ans=max(ans,i-max(que1[head1].index,que2[head2].index)+1),如果我们删除下标大的那个队首元素,那么对应的队列必然要head++,即满足条件的下标在变大,那么max(que1[head1].index,que2[head2].index)必然也跟着增大,不能满足max(que1[head1].index,que2[head2].index)尽可能小,而删除下标小的队首元素,可以在max(que1[head1].index,que2[head2].index)尽可能小的情况下满足m<=d<=k。详见程序:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100000+100;
int n,m,k;
int head1,tail1,head2,tail2;
int a[MAXN];
struct node
{
    int val,index;
}que1[MAXN],que2[MAXN];
int main()
{
    //freopen("text.txt","r",stdin);
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int ans=0,last1=0,last2=0;
        head1=tail1=head2=tail2=0;
        for(int i=1;i<=n;i++)
        {
            while(head1<tail1 && que1[tail1-1].val>a[i]) tail1--;
            que1[tail1].val=a[i]; que1[tail1++].index=i;
            while(head2<tail2 && que2[tail2-1].val<a[i]) tail2--;
            que2[tail2].val=a[i]; que2[tail2++].index=i;
            while(que2[head2].val-que1[head1].val>k)
            {
                if(que2[head2].index<que1[head1].index)
                    last2=que2[head2++].index;
                else
                    last1=que1[head1++].index;
            }
            if(que2[head2].val-que1[head1].val>=m)
                ans=max(ans,i-max(last1,last2));
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值