ST 表
ST 表
ST 表是用于解决大部分静态 RMQ 问题的数据结构。
引入
给定 \(n\) 个数,\(m\) 次询问,每次回答 \([l, r]\) 中的最大值。
首先,我们可以想到一个暴力的做法:每次枚举 \(l \sim r\) 中的所有数字,求出最大值。
但是,当 \(n\) 足够大时,是会超时的。
所以就需要 ST 表了。
ST 表
ST 表基于倍增思想,\(O(n \log n)\) 预处理,\(O(1)\) 询问,但是不支持修改操作,线段树和树状数组可以修改元素。
我们先看前一部分,
预处理
我们定义 \(f_{i, j}\) 表示 \([i, i + 2 ^ j - 1]\) 的最大值,就有递推式:\(f_{i, j} = max(f_{i, j - 1}, f_{i + 2 ^ {j - 1}}, j - 1)\)。
void P() {
for (int j = 1; j < 20; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
}
询问
我们可以发现,如果我们要求 \([l, r]\) 的最大值,其实就算所有合并的区间之间有重叠也没关系,也就是说,我们只需要求 \(max(f_{l, k}, f_{r - 2 ^ k + 1, k}) \ (2 ^ k \le r - l + 1)\) 即可,所以,我们需要预处理出所有 \(i \ (1 \le i \le n)\) 的 \(\log\)。
void P() {
for (int j = 1; j < L; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
log_2[1] = 0;
for (int i = 2; i <= n; i++) {
log_2[i] = log_2[i / 2] + 1;
}
}
int Solve() {
int p = log_2[r - l + 1];
return max(f[l][p], f[r - (1 << p) + 1][p]);
}

浙公网安备 33010602011771号