HDU3530 Subsequence(单调队列)

时间:2023-03-09 19:50:06
HDU3530 Subsequence(单调队列)

题意是说给出一个序列,现在要求出这个序列的一个最长子区间,要求子区间的最大值与最小值的差在[m, k]范围内,求区间长度

做法是维护两个队列,一个维护到当前位置的最大值,一个维护最小值,然后计算当前节点i作为右端点的最常区间长度,那么扫描两个队列,维持单调性。

然后比较两个队列头的差值,

1.如果差值满足条件,那么记录答案;

2.如果差值小于m,那么此时没有答案,说明没有以i作为右端点的区间满足条件(表示前i个数的最大值减去前i个数的最小值的差<m,那么不论如何调整起点,都不可能有解)

3.如果差值大于k,说明此时区间的最大值与最小值的差过大,那我们可以通过缩小最大值(最大值(递减)队列向右移动)或者增大最小值(最小值(递增)队列向右移动)的方法使得差值变小,那到底是移动哪一个指针取决于此时队首的这两个值谁的编号要小(保证区间是合法的)。

另外有一点要注意的细节是,上述的第三种情况,在移动队首的指针时,如果最后被删除的元素所指向的下标p,此时队首的元素指向的下标是q, 此时合法区间为[p +1, i]而不是[q, i]

 //#pragma comment(linker, "/STACK:1677721600")
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf (-((LL)1<<40))
#define lson k<<1, L, (L + R)>>1
#define rson k<<1|1, ((L + R)>>1) + 1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#define dec(i, a, b) for(int i = a; i >= b; i --) template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; } //typedef __int64 LL;
typedef long long LL;
const int MAXN = + ;
const int MAXM = ;
const double eps = 1e-;
LL MOD = ; int a[MAXN], L, H, n;
int q1[MAXN], q2[MAXN]; int find_ans() {
int f1, f2, t1, t2, l1 = -, l2 = -, ans = ;
f1 = f2 = t1 = t2 = ;
rep (i, , n - ) {
while(f1 < t1 && a[q1[t1 - ]] <= a[i]) t1 --;//维护最大值队列(递减)
q1[t1++] = i;
while(f2 < t2 && a[q2[t2 - ]] >= a[i]) t2 --;//维护最小值队列(递增)
q2[t2++] = i;
while(a[q1[f1]] - a[q2[f2]] > H) {//差值过大
q1[f1] < q2[f2] ? l1 = q1[f1 ++] : l2 = q2[f2 ++];
}
if(a[q1[f1]] - a[q2[f2]] >= L) {//差值满足条件
ans = max(ans, i - max(l1, l2));
}
}
return ans;
} int main()
{
while(~scanf("%d %d %d", &n, &L, &H)) {
rep (i, , n - ) scanf("%d", a + i);
printf("%d\n", find_ans());
}
return ;
}