ST表
简介
ST表通常用于处理区间最值问题等可以重复贡献的问题,也就是说你对一个相同的数进行两次操作,其结果不变,如多个数的 \(\gcd\) 问题。
跟线段树和树状数组一样,可以处理区间最值问题,但其只支持区间查询,不支持修改操作。
不过他可以以 \(O(1)\) 的复杂度查询,只需要 \(O(n\log n)\) 的预处理。
基本思想
我们用区间最大值举例。
预处理
我们令 \(f(i,j)\) 为区间 \([i,i+2^j-1]\) 的最大值。
可得 \(f(i,0)=a_i\) ;
可得递推式 $f(i,j)=\max(f(i,j-1),f(i+2^{j-1},j-1)) $ 。
查询
查询实际上就是对于一个查找的区间,找出两个能完全覆盖其的区间的最值。
我们要知道,ST表为何只能实现可重复贡献的操作,是因为他的查询基本上都有重叠部分。
对于要查询的区间 \([l,r]\) ,我们令 \(k=\log(r-l+1)\) ,那么就可以将其分为 两个区间, \([l,l+2^k-1]\) 和 \([r-2^k+1,r]\) ,求出他们的值就可以了。
void init() {
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;
}//预处理出log
}
int Solve(int l,int r) {
int p = log_2[r - l + 1];
return max(f[l][p], f[r - (1 << p) + 1][p]);
}

浙公网安备 33010602011771号