zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    APMServ5.2.6 无法启动Apache的一个问题
    【转】流媒体技术笔记(视频编码相关)
    用APMServ一键快速搭建Apache+PHP+MySQL+Nginx+Memcached+ASP运行平台
    java swing 基础
    python class 类
    python 经验
    python 导入(转)
    kernel ipv4/ip_output.c
    python+正则表达式(转)
    Eclipse中如何快速添加、删除jar包
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/4667190.html
Copyright © 2011-2022 走看看