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]);
}
posted @ 2023-10-09 15:41  xyh0528  阅读(81)  评论(0)    收藏  举报