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
  • 相关阅读:
    poj 1584
    poj 1113 & poj 2187
    pku 1321 棋盘问题
    poj 1408
    pku 2251 Dungeon Master
    sdut oj 2218 Give Me an E
    Android工程 单元测试
    Android Timer编写方式
    去除工程的.svn隐藏文件夹
    Android 绑定远程服务出现 Not Allowed to bind service
  • 原文地址:https://www.cnblogs.com/-maybe/p/4675693.html
Copyright © 2011-2022 走看看