Subsequence HDU 3530 (单调队列)

本文详细介绍了如何使用滑动窗口算法解决区间内最大值与最小值的问题,并通过具体实例展示了算法实现过程。文章通过维护两个队列来动态更新当前区间内的最大值与最小值,以此判断是否满足题目设定的条件。

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

题目
q1维护一个单调递减的最大值队列,q2维护一个单调递增的最小值队列,所以q1的第一个元素第一是当前区间的最大值,q2的第一个元素一定是当前区间的最小值。如下图例子
5 1 3
1 3 8 4 5
i=1,把1加入q1,q2,此时1-1<=3,当前区间左端now=1, 右端i=1,ans更新为1。(q1,q2存的是位置,比较的值ai的值)
i=2, 由于q1的第一个元素的值小于3,所以当前区间的最大值不是1了,把1弹出,把2加入q1,q2。此时区间[1,2]中最大值是3,最小值是1,满足条件,答案更新为2。
i=3,同理,最大值更新为8,最小值仍是1,但是8-1>3,且最小值的位置靠前,所以把当前最小值弹出,更新区间为(2,3),但是8-3>3,所以继续更新。
以下同理

在这里插入图片描述

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#define LL long long 
#define mem(a, b) memset(a, b, sizeof(a))
#define N 100005 
#define MOD
using namespace std;
int n, m, k, a[N], q1[N], q2[N];
int h1, h2, t1, t2;

int main() {
	while(scanf("%d%d%d", &n, &m, &k)!=EOF) {
		for(int i=1; i<=n; i++) {
			scanf("%d", &a[i]);
		}
		int ans=0, h1=0, h2=0, t1=0, t2=0;
		mem(q1, 0), mem(q2, 0);
		int now=1;
		for(int i=1; i<=n; i++) {
			while(h1<t1 && a[q1[t1-1]]<a[i]) //维护一个递减的最大值的队列 
				t1--;
			while(h2<t2 && a[q2[t2-1]]>a[i]) //维护一个递增的最小值的队列
				t2--;
			 q1[t1++]=q2[t2++]=i;
			while(h1<t1 && h2<t2 && a[q1[h1]]-a[q2[h2]]>k) {
				if(q1[h1]<q2[h2]) {
					now=q1[h1++]+1;
				}
				else {
					now=q2[h2++]+1;
				}
			} 
			if(h1<t1 && h2<t2 && a[q1[h1]]-a[q2[h2]]>=m)
				ans=max(ans, i-now+1);
		}
		cout<<ans<<endl;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值