RMQ(Range Minimum/Maximum Query)问题是求区间最值问题。

对于长度为 n 的数组 A,进行若干次查询,对于区间 [L,R] 返回数组A中下标在 [L,R] 中的最小(大)值。

可以用线段树来解决这个问题,预处理的复杂度是 O(nlogn),查询的复杂度是 O(logn)。

更好的解法是ST算法。Sparse_Table算法,即稀疏表算法,这个方法可以在 O(nlogn) 的预处理后达到 O(1) 的查询代价。

这个算法非常容易实现。

 

定义 F[ i, k ] 表示从 i 开始的,长度为 2^k 的区间内元素的最小值。

当 k = 0 时,F[ i, 0 ] 的值显然就是A[ i ] 的值。

而 k > 0 时,对于从 i 开始的长度为 2^k 的区间,它的最小值显然是从 i 开始的长度为 2^(k-1) 的区间中的最小值与从 i+2^(k-1)开始的长度为 2^(k-1) 的区间中的最小值中更小的那一个。

则有递推公式 F[ i, k ] = min{ F[ i, k-1 ], F[ i+2^(k-1), k-1] }

由于 2^k<=n,因此 F 数组中的元素个数不会超过 nlogn,而每个元素都可以在O(1)的时间内计算出,因此总时间为O(nlogn)。

1 int F[maxn][20];
2 //元素从1编号到n
3 void RMQ_init(int A[],int n){
4     for (int i=1;i<=n;i++) F[i][0]=A[i];
5     for (int k=1;(1<<k)<=n;k++)
6         for (int i=1;i+(1<<k)-1<=n;i++)
7             F[i][k]=min(F[i][k-1],F[i+(1<<(k-1))][k-1]);
8 }
RMQ的预处理

相关文章:

  • 2022-12-23
  • 2021-11-06
  • 2021-07-25
  • 2021-11-13
  • 2022-12-23
  • 2021-07-30
  • 2021-10-08
猜你喜欢
  • 2021-11-17
  • 2022-01-15
  • 2022-12-23
  • 2022-01-05
  • 2021-10-12
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案