hdu~3530(单调队列)

单调队列就是队列中的元素是单调递增或递减的。比如把 5 2 3 1 4 入队:

减:、、、、、、、、、、、增:

5 、、、、、、、、、、、、5

5 2 、、、、、、、、、、、2 

5 3 、、、、、、、、、、、2 3

5 3 1、、、、、、、、 、、1

5 4 、、、、、、、、、、、1 4


这个还是好理解的,但是,我们得会用单调队列这一特性去解决题目,抽象出题目中有类似的操作。

Subsequence

题意:

给三个数   n,x,y;

接下来n个数num[1~n];

求满足这个条件的最长区间长度:区间内最大值与最小值之差在 x~y之间。

方法:

单调队列记录下标。

由一个递增,一个递减的单调队列,可得前面的某个位置~当前位置的最大差值def=num[q1.front()]-num[q2.front()];

如果def>y,则让下标靠前的那个出队列。


上代码,看注释:

#include <stdio.h>
#include <iostream>
#include <deque>

using namespace std;

inline int  fmax(int a,int b){return a>b?a:b;}  

int main()
{
    int n,x,y;
    int num[100005];
    while(scanf("%d %d %d",&n,&x,&y)!=EOF)
    {
        for(int i=1;i<=n;++i)
            scanf("%d",&num[i]);
        deque<int >q1,q2;   //两个队列,q1.front()存最大值,q2.front()存最小值
        int max=0,last=0;   //last记录最后弹出元素的位置
        for(int i=1;i<=n;i++){
            while(!q1.empty() && num[i]>num[q1.back()]) q1.pop_back();//维护队列单调型
            while(!q2.empty() && num[i]<num[q2.back()]) q2.pop_back();
            q1.push_back(i);
            q2.push_back(i);
        //若对不空,且def>y,让下标靠前的出队。
            while(!q1.empty() && !q2.empty() && num[q1.front()]-num[q2.front()]>y){
                if(q1.front()>q2.front())
                {
                    last=q2.front();
                    q2.pop_front();
                }
                else if(q1.front()<q2.front())
                {
                    last=q1.front();
                    q1.pop_front();
                }
                else if(q1.front()>q2.front())
                {
                    last=q2.front();
                    q1.pop_front();
                    q2.pop_front();
                }
            }
        
            if(!q1.empty() && !q1.empty() && num[q1.front()]-num[q2.front()]>=x)
                max=fmax(max,i-last);//若当前区间的def满足>=x,取区间最大长度
        }
        printf("%d\n",max);
    }

    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值