基于稀疏表(Sparse Table)的RMQ需要先进行复杂度O(nlogn)的预处理,而后在查询[ql, qr]的最值时,计算出最大的满足ql + (1 << bit) <= qr的bit(复杂度O(loglogn)),即可在O(1)时间复杂度内查询,从而可以解决查询次数很多(如大于100万)的RMQ问题。

 

我们定义t[i][j]为以 i 为左端点的长度为 2j 的闭区间(0 <= j, 2j <= n, 1 <= i <= n - 2j + 1)

我们可以得到如下的一个稀疏表

基于稀疏表(Sparse Table)的RMQ讲解

这样以来每个t[][]表示的都是一段长度为2的幂次的区间的最值。但考虑到实际查询的区间长度往往不是2的幂次,那么这个区间要如何表示呢?答案是一个不行,就来两个。把查询区间用两个区间的并来表示。为了确保两个区间的并恰好为查询区间,我们可以从左右边界向中间扫(如图)

基于稀疏表(Sparse Table)的RMQ讲解

那么为了确保两个小区间可以包含整个大区间,小区间长度必然不小于原区间的一半,且区间长度为2的幂次。所以在RMQ中,我们首先要求出满足2<= qr - ql < 2j + 1 的j。也就是使得2j不超过(qr - ql)的最大的j。

有了这种划分区间的思想,我们可以轻易地出状态转移公式

t[i][j] = {t[i][j - 1], t[i + (1 << (j - 1))][j - 1]}; 

 

对于每个查询,{dp[ql][j], dp[qr - (1 << j) + 1][j])就是答案了。//左右皆闭

 

这样以来问题就仅剩下,如何高效地求解对应j呢?

计算(qr - ql),然后二分求解即可

 1 int mbit(int a) {
 2     int l = 0, r = 16;
 3     while (l < r - 1) {
 4         int m = (l + r) / 2;
 5         if ((1 << m) <= a) {
 6             l = m;
 7         } else {
 8             r = m;
 9         }
10     }
11     return l;
12 }
View Code

相关文章:

  • 2021-11-27
  • 2022-12-23
  • 2021-08-24
  • 2021-08-13
  • 2022-12-23
  • 2022-01-03
  • 2021-07-06
猜你喜欢
  • 2021-04-05
  • 2021-08-21
  • 2021-07-06
  • 2022-03-08
  • 2021-10-09
  • 2021-12-24
  • 2021-12-31
相关资源
相似解决方案