HDU - 5289 Assignment (RMQ+二分)

Posted Bestcoderg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 5289 Assignment (RMQ+二分)相关的知识,希望对你有一定的参考价值。

题目链接: Assignment

 题意:

  给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k。

题解:

  RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相当于求出了每个区间的最大值-最小值。那么现在我们枚举左端点,二分右端点就可以在n×logn×logn的时间内过。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAX_N = 1e5+9;
 4 int vec[MAX_N];
 5 int dp1[MAX_N][25];
 6 int dp2[MAX_N][25];
 7 long long ans = 0;
 8 int N,M,T;
 9 void ST(int N)
10 {
11     for(int i=1;i<=N;i++) dp1[i][0] = dp2[i][0] = vec[i];
12     for(int j=1;(1<<j)<=N;j++)
13     {
14         for(int i=1;i+(1<<j)-1<=N;i++)
15         {
16             dp1[i][j] = max(dp1[i][j-1],dp1[i+(1<<j-1)][j-1]);
17             dp2[i][j] = min(dp2[i][j-1],dp2[i+(1<<j-1)][j-1]);
18         }
19     }
20 }
21 int RMQ(int l,int r)
22 {
23     int k = 0;
24     while(1<<k+1 <= r-l+1) k++;
25     int maxn = max(dp1[l][k],dp1[r-(1<<k)+1][k]);
26     int minn = min(dp2[l][k],dp2[r-(1<<k)+1][k]);
27     return maxn-minn;
28 }
29 int main()
30 {
31     cin>>T;
32     while(T--)
33     {
34         cin>>N>>M;
35         ans = 0;
36         for(int i=1;i<=N;i++) scanf("%d",&vec[i]);
37         ST(N);
38         for(int i=1;i<=N;i++)
39         {
40             int l =i,r = N;
41             while(l<=r)
42             {
43                 int mid = (l+r)>>1;
44                 if(RMQ(i,mid) < M) l = mid+1;
45                 else r = mid-1;
46             }
47             ans += (l-1) - i +1;
48         }
49         cout<<ans<<endl;
50     }
51     return 0;
52 }

 

以上是关于HDU - 5289 Assignment (RMQ+二分)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5289 Assignment

HDU - 5289 Assignment (RMQ+二分)

HDU 5289 Assignment(多校联合第一场1002)

HDU 5289 Assignment(二分+RMQ-ST)

HDU 5289 Assignment(单调队列)

hdu5289 Assignment (区间查询最大值最小值,st算法...)