HDU 3530 单调队列

本文介绍了一种使用双单调队列解决特定数值范围内最长子序列问题的方法。通过维护递增与递减队列,实现了对子序列最大值与最小值的有效追踪,从而判断其是否满足给定条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击打开链接

题意:给n个数和m,k,问你数列中最长的子序列,其中最大值减去最小值大于等于m小于等于k

思路:想着想着想到尺取去了,写了一半实现不了((/ □ \)),一看单调队列也没怎么练过,大致就只知道单调队列肯定是维护一个什么东西,只能看大神们的思路了,维护了两个队列,一个是以当前结束所构成的递减序列的位置,另一个是以当前结束构成的递增序列的位置,然后每次的最大值减去最小值,如果大于k,那么就更新两个中的一个,应该更新位置较小的那个,这样才能使得这个区间的长度最大,然后就这么更新就行了  PS:这思想不好想啊

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int num[maxn],Q1[maxn],Q2[maxn];
int n,m,k;
int main(){
    while(scanf("%d%d%d",&n,&m,&k)!=-1){
        for(int i=1;i<=n;i++) scanf("%d",&num[i]);
        int s1=0,e1=0,s2=0,e2=0,ans=0,pos=0;
        for(int i=1;i<=n;i++){
            while(s1<e1&&num[Q1[e1-1]]<num[i]) e1--;
            while(s2<e2&&num[Q2[e2-1]]>num[i]) e2--;
            Q1[e1++]=i;Q2[e2++]=i;
            while(s1<e1&&s2<e2&&num[Q1[s1]]-num[Q2[s2]]>k){
                if(Q1[s1]<Q2[s2]) pos=Q1[s1++];
                else pos=Q2[s2++];
            }
            if(s1<e1&&s2<e2&&num[Q1[s1]]-num[Q2[s2]]>=m) ans=max(ans,i-pos);
        }
        printf("%d\n",ans);
    }
    return 0;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值