Subsequence HDU - 3530 (单调栈,初学详细解释)

题意:给你n,m,k以及一数组,n个元素,求一个序列使得序列里最大值减去最小值>=m且<k,求这个序列的最大长度,序列必须连续。

思路:用单调栈维护一个单调递增序列和一个单调递减序列,计算两个单调栈的栈底元素的差值分别跟m,k 作比较得出序列的最大值。详细看代码,注释很详细

#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int a[N],maxx[N],minn[N],n,m,k;//maxx数组维护单调递减序列,存的是下标,栈底元素最大,minn数组反之
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        //front为头指针,tail尾指针
        int front1=0,tail1=-1,front2=0,tail2=-1,flag=-1,ans=0;
        for(int i=0;i<n;i++)
        {
            //头指针小于尾指针且当前元素大于栈顶元素时让尾指针减一,即让使栈顶元素出栈,因为要维护一个单调递减序列
            while(front1<=tail1&&a[i]>a[maxx[tail1]]) tail1--;
            maxx[++tail1]=i;
            while(front2<=tail2&&a[i]<a[minn[tail2]]) tail2--;
            minn[++tail2]=i;
            //两个栈的栈顶元素,一个是存的是数组中最大的元素下标一个是数组中最小的元素下标
            //用最大的减去最小的分别跟m,k比较
            while(a[maxx[front1]]-a[minn[front2]]>k)
            {
                flag=min(maxx[front1],minn[front2]);//选择更小的下标让其++
                if(flag==maxx[front1]) front1++;
                if(flag==minn[front2]) front2++;
            }
            if(a[maxx[front1]]-a[minn[front2]]>=m)//记录答案
                ans=max(ans,i-flag);
        }
        printf("%d\n",ans);
    }
}

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
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值