• HDU 5289


    http://acm.hdu.edu.cn/showproblem.php?pid=5289

    给一个数列,求有多少区间,使得这些区间内的最大值减最小值小于k

    单调队列的功能:O(1) 插入,删除,最大or最小

    方法:枚举区间的后界,找前界(一定可以找到一个后界使得这个后界的前面所有满足要求,后面所有不满足要求)。因为当前区间的前界,一定在前一个区间的前界的后面(一个区间满足要求,它的所有子区间一定满足要求),这个性质可以保证我们的区间枚举是O(n)的。区间有了,区间内的最大最小值可以通过两个单调队列O(1)维护。这样这道题在O(n)内就获得了解决。

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    typedef __int64 ll;
    
    int n, k;
    int a[100005], qmax[100005], qmin[100005];
    
    void gao() {
        ll ans = 0;
        int maxf, maxr, minf, minr;
        maxf = maxr = minf = minr = 0;
        qmax[maxr++] = a[0];
        qmin[minr++] = a[0];
        int p, q;//p区间起点,q-1区间终点 
        p = 0, q = 1;
        while(p != n || q != n) {
            if(q != n) {
                while(maxf != maxr && qmax[maxr-1] < a[q]) maxr--;//单调队列操作,队列不为空并且不能保证单调则出队 
                qmax[maxr++] = a[q];                               //入队 
                while(minf != minr && qmin[minr-1] > a[q]) minr--;
                qmin[minr++] = a[q];
            }
            while(p != n && (qmax[maxf]-qmin[minf] >= k || q == n)) {
                ans += q-p;
                if(qmax[maxf] == a[p]) maxf++;
                if(qmin[minf] == a[p]) minf++;
                p++;
            }
            if(q != n) q++;
        }
        printf("%I64d
    ", ans);
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d", &n, &k);
            for(int i = 0; i < n; i++)
                scanf("%d", &a[i]);
            gao();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Selenium WebDriver 中鼠标事件(全)
    日常知识积累加不定期更新(一)
    动作手游实时PVP技术揭密(服务器篇)
    Java RMI之HelloWorld篇
    java中注解的使用与实例 (二)
    RPC原理及RPC实例分析
    动作手游实时PVP帧同步方案(客户端)
    java中注解的使用与实例(一)
    动作手游实时PVP技术揭密(服务器篇)
    AS3.0 几何结构 Point对象和Rectangle对象
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/4667190.html
Copyright © 2020-2023  润新知