zoukankan      html  css  js  c++  java
  • HDU 5289

    Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this company, and every staff has a ability. Now, Tom is going to assign a special task to some staffs who were in the same group. In a group, the difference of the ability of any two staff is less than k, and their numbers are continuous. Tom want to know the number of groups like this.

    InputIn the first line a number T indicates the number of test cases. Then for each case the first line contain 2 numbers n, k (1<=n<=100000, 0<k<=10^9),indicate the company has n persons, k means the maximum difference between abilities of staff in a group is less than k. The second line contains n integers:a[1],a[2],…,a[n](0<=a[i]<=10^9),indicate the i-th staff’s ability.OutputFor each test,output the number of groups.Sample Input

    2
    4 2
    3 1 2 4
    10 5
    0 3 4 5 2 1 6 7 8 9

    Sample Output

    5
    28

    Hint

    First Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3] 

    题意: 求出所有满足最大值与最小值的差小于k的子区间的个数。

    这个人的思路写的比较清晰: https://blog.csdn.net/maxichu/article/details/47612497


    用两个单调队列维护最大值与最小值, 然后就是枚举左端点的过程。

    设两个指针i,j 并让他们从头扫到尾,这样是O(n)的复杂度, 如果不知道单调队列是啥就自行百度吧。

    [j, i-1]是当前处理的区间。将第 i 个元素加入后如果最大值-最小值 >= k 就说明[j,i]不可行。那么[j,k](k>x && k<=n)同样是不可行的。
    所以这时我们就处理完了所有以 j 做为左端点的区间了,开始更新j 并统计。


    #include<cstdio>
    #include<queue>
    using namespace std;
    #define ll long long
    deque<int>Max, Min;
    int arr[100005];
    
    int main(){
        int t, n, k;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&k);
            for(int i=0;i<n;i++){
                scanf("%d",&arr[i]);
            }
            int i = 0, j = 0;
            ll ans = 0;
            Max.clear();Min.clear();
            for(;i<n;i++){
                while(!Max.empty() && Max.back() < arr[i])
                    Max.pop_back();
                Max.push_back(arr[i]);
                while(!Min.empty() && Min.back() > arr[i])
                    Min.pop_back();
                Min.push_back(arr[i]);
                while(!Max.empty() && !Min.empty()
                      && Max.front()-Min.front() >= k){
                    ans += (i-j);
                    // 这是所有以 j 为左端点的区间的数量(右端点为i-1)
                    if(Max.front() == arr[j])Max.pop_front();
                     // 后续的处理中 j 不在区间中, 所以要将arr[j]取出
                    if(Min.front() == arr[j])Min.pop_front();
                    j++;// 更新 j
                }
            }
            while(j<n){ // [j, n] 是个可行解
                ans += i-j;
                j++;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code


  • 相关阅读:
    ASP.NET MVC 3 学习笔记系列之Music Store(1)
    sql 拆分 逗号 函数
    软件开发项目的人力资源管理 团队配置问题探讨
    从某失败项目中学到的经验教训
    需求为王
    信息系统项目管理师考试经验分享
    JSP中文乱码问题及编码知识详解
    详解java中instanceof各种的用法
    mvc开源项目
    asp.net服务组件自动事务处理
  • 原文地址:https://www.cnblogs.com/kongbb/p/10746636.html
Copyright © 2011-2022 走看看