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
原文地址:https://www.cnblogs.com/-maybe/p/4675693.html