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


  • 相关阅读:
    华为:证实已开发出自主操作系统
    Aseprite入门:第一个gif动图
    《亿级用户下的新浪微博平台架构》阅读笔记
    Aseprite入门教程
    “华为起诉美国”事件进展:美国联邦法院给美国政府发传票
    CoCos2dx开发:中文乱码
    谈谈对“华为向美国联邦法院起诉美国”的看法
    《支付宝和蚂蚁花呗的技术架构及实践》阅读笔记
    Cocos2d-x环境配置步骤
    《菜鸟弹性调度系统的架构设计》阅读笔记
  • 原文地址:https://www.cnblogs.com/kongbb/p/10746636.html
Copyright © 2011-2022 走看看