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 }