zoukankan      html  css  js  c++  java
  • HDU 5289 2015 Multi-University Training Contest 1 1002 RMQ+二分

                      Assignment

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1758    Accepted Submission(s): 849


    Problem Description
    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.
     
    Input
    In 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.
     
    Output
    For 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]
     
    Author
    FZUACM
     
    Source

     

    题意:

    给出一个序列,求这个序列里面有多少组,满足组内的最大值-最小值<K

    刚开始的想法

    设dp[i]表示以i为左端点,最远可以到达的位置,使得区间[i,i],[i,i+1],,,[i,dp[i]]都满足条件

    则以i为左端点有dp[i]-i+1个区间满足条件,再对所有的i,累加dp[i]-i+1,即为答案

    问题是:递推不出dp[i]

    后来看了题解,可以用rmq+二分求出i最远可以到达的位置,而不是递推。

    先用st算法求出任意区间的最大值和最小值的差。

    枚举左端点i,二分右端点j,则以i为左端点有j-i+1个区间满足。

    累加,即为答案。

    注意:最后答案要用long long

     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 #define MAX(x,y) x>y?x:y;
     5 #define MIN(x,y) x<y?x:y;
     6 #define LL long long
     7 
     8 using namespace std;
     9 
    10 const int MAXN=100000+10;
    11 int a[MAXN];
    12 int min[MAXN][20];
    13 int max[MAXN][20];
    14 
    15 void init(int N)
    16 {
    17     for(int i=1;i<=N;i++)
    18     {
    19         min[i][0]=a[i];
    20         max[i][0]=a[i];
    21     }
    22     for(int j=1;(1<<j)<=N;j++)
    23     {
    24         for(int i=1;(i+(1<<j)-1)<=N;i++)
    25         {
    26             min[i][j]=MIN(min[i][j-1],min[i+(1<<(j-1))][j-1]);
    27             max[i][j]=MAX(max[i][j-1],max[i+(1<<(j-1))][j-1]);
    28         }
    29     }
    30 }
    31 
    32 int query(int l,int r)
    33 {
    34     int k=0;
    35     while((1<<(k+1))<=r-l+1)
    36         k++;
    37     int x=MAX(max[l][k],max[r-(1<<k)+1][k]);
    38     int y=MIN(min[l][k],min[r-(1<<k)+1][k]);
    39     return x-y;
    40 }
    41 
    42 LL solve(int N,int K)
    43 {
    44     LL res=0;
    45     for(int i=1;i<=N;i++)
    46     {
    47         int l=i,r=N;
    48         while(r-l>1)
    49         {
    50             int p=(l+r)>>1;
    51             if(query(i,p)<K)
    52                 l=p;
    53             else
    54                 r=p;
    55         }
    56         if(query(i,r)<K)
    57             res+=(LL)(r-i+1);
    58         else
    59             res+=(LL)(l-i+1);
    60     }
    61     return res;
    62 }
    63 
    64 int main()
    65 {
    66     int test;
    67     scanf("%d",&test);
    68     while(test--)
    69     {
    70         int N,K;
    71         scanf("%d%d",&N,&K);
    72         for(int i=1;i<=N;i++)
    73         {
    74             scanf("%d",&a[i]);
    75         }
    76         init(N);
    77 
    78         printf("%I64d
    ",solve(N,K));
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    AutoLISP 绘制滚轮
    铁打的学校流水的学生
    AutoLISP绘制花型三
    AutoCAD LISP花型图案二
    AutoCAD LISP多边形边为直径绘制圆
    AutoCAD矩形交叉口框短边切圆一
    AutoCAD LISP花型图案一
    AutoLISP圆形堆栈金字塔
    AutoCAD矩形交叉口框短边切圆二
    AutoCADLISP绘制楼梯
  • 原文地址:https://www.cnblogs.com/-maybe/p/4675693.html
Copyright © 2011-2022 走看看