HDU3530 Subsequence(单调队列)

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

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

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

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

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

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

 

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

 

 1 //#pragma comment(linker, "/STACK:1677721600")
 2 #include <map>
 3 #include <set>
 4 #include <stack>
 5 #include <queue>
 6 #include <cmath>
 7 #include <ctime>
 8 #include <vector>
 9 #include <cstdio>
10 #include <cctype>
11 #include <cstring>
12 #include <cstdlib>
13 #include <iostream>
14 #include <algorithm>
15 using namespace std;
16 #define INF 0x3f3f3f3f
17 #define inf (-((LL)1<<40))
18 #define lson k<<1, L, (L + R)>>1
19 #define rson k<<1|1,  ((L + R)>>1) + 1, R
20 #define mem0(a) memset(a,0,sizeof(a))
21 #define mem1(a) memset(a,-1,sizeof(a))
22 #define mem(a, b) memset(a, b, sizeof(a))
23 #define FIN freopen("in.txt", "r", stdin)
24 #define FOUT freopen("out.txt", "w", stdout)
25 #define rep(i, a, b) for(int i = a; i <= b; i ++)
26 #define dec(i, a, b) for(int i = a; i >= b; i --)
27 
28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
32 
33 //typedef __int64 LL;
34 typedef long long LL;
35 const int MAXN = 100000 + 100;
36 const int MAXM = 110000;
37 const double eps = 1e-8;
38 LL MOD = 1000000007;
39 
40 int a[MAXN], L, H, n;
41 int q1[MAXN], q2[MAXN];
42 
43 int find_ans() {
44     int f1, f2, t1, t2, l1 = -1, l2 = -1, ans = 0;
45     f1 = f2 = t1 = t2 = 0;
46     rep (i, 0, n - 1) {
47         while(f1 < t1 && a[q1[t1 - 1]] <= a[i]) t1 --;//维护最大值队列(递减)
48         q1[t1++] = i;
49         while(f2 < t2 && a[q2[t2 - 1]] >= a[i]) t2 --;//维护最小值队列(递增)
50         q2[t2++] = i;
51         while(a[q1[f1]] - a[q2[f2]] > H) {//差值过大
52             q1[f1] < q2[f2] ? l1 = q1[f1 ++] : l2 = q2[f2 ++];
53         }
54         if(a[q1[f1]] - a[q2[f2]] >= L) {//差值满足条件
55             ans = max(ans, i - max(l1, l2));
56         }
57     }
58     return ans;
59 }
60 
61 int main()
62 {
63     while(~scanf("%d %d %d", &n, &L, &H)) {
64         rep (i, 0, n - 1) scanf("%d", a + i);
65         printf("%d\n", find_ans());
66     }
67     return 0;
68 }

 

posted @ 2015-07-20 11:27  再见~雨泉  阅读(627)  评论(1编辑  收藏  举报