ST 算法
ST 算法是一种运用倍增来解决 RMQ 问题也就是区间最值问题的算法。
给定一个长度为 \(N\) 的序列 \(A\),ST 算法能在 \(\mathcal O(N log N)\) 的时间预处理后,以 \(\mathcal O(1)\) 的时间在线回答区间最值问题。
设 \(F_{i,j}\) 表示序列 \(A\) 中下标在子区间 \(\left[i,i + 2^j - 1 \right]\) 里的数的最大值,也就是从 \(i\) 开始 \(2^j\) 个数的最大值。边界是 \(F_{i,0} = A_i\)。
在递推时我们将子区间的长度成倍增长,\(F_{i,j} = \max(F_{i,j - 1},F_{i + 2^{j-1},j - 1})\),即长度为 \(2^j\) 的子区间的最大值是左右两边长度为 \(2^{j-1}\) 的子区间的最大值中大的那一个。
for(int i=1;i<=n;i++){
f[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;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]);
}
}
当询问区间 \(\left[l,r \right]\) 的最值时,先找出一个 \(k\),满足 \(2^k \le r - l + 1 \le 2^{k+1}\),那么从 \(l\) 开始的 \(2^k\) 个数和以 \(r\) 结尾的 \(2^k\) 个数一定覆盖了整个区间。
而这两段的最大值分别为 \(F_{l,k}\) 和 \(F_{r - 2^k + 1,k}\),所以整个区间的最值就是这两段中大的那一个。
int ST(int l,int r){
int k=log(r-l+1)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}
标签:int,最大值,笔记,ST,算法,区间,最值
From: https://www.cnblogs.com/MithrilSwordXIV/p/17971259