• 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
    ", find_ans());
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    2014年5月16日
    2014年4月8日
    Qt 小技巧之“To-Do 事项”
    koa中间件实现分析
    关于计算透视投影的四条边的方法,留作备忘
    关于向量
    关于ngui协同
    关于NGUI分辨率
    动态修改NGUI UI2DSprite
    动态设置viewport的宽高
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/4660953.html
Copyright © 2020-2023  润新知