作用
- ST算法是用来求解给定区间的最值的
优势
- ST算法分成两部分:离线预处理 $O(nlogn)$和 在线查询$O(1)$。虽然还可以使用线段树、树状链表等求解区间最值,但是ST算法要比它们更快,而且适用于在线查询。
操作
预处理
- 就是DP, 用于求解区间最值,并保存到一个二维数组中
- 使用倍增的思想,每次增加2^i个长度
使用$f[i,j]$表示以$i$为起点,区间长度为$2^j$的区间最值,此时区间为$[i,i + 2^j - 1]$。
比如,$f[0,2]$表示区间$[0,3]$的最小值,即等于$4$,$f[2,2]$表示区间$[2,5]$的最小值,即等于$1$。
在求解$f[i,j]$时,ST算法先对长度为$2^j$的区间$[i,i + 2^j - 1]$分成两等份,每份长度均为$2^{j - 1}$。之后在分别求解这两个区间的最值$f[i,j - 1]$和$f[i + 2^{j - 1},j - 1]$。,最后在结合这两个区间的最值,求出整个区间的最值。特殊情况,当$j = 0$时,区间长度等于$1$,即区间中只有一个元素,此时$f[i,0]$应等于每一个元素的值。
举例:要求解$f[1,2]$的值,即求解区间$[1,4] = \{4,6,10,1\}$的最小值,此时需要把这个区间分成两个等长的区间,即为$[1,2]$和$[3,4]$,之后分别求解这两个区间的最小值。此时这两个区间最小值分别对应着$f[1,1]$ 和 $f[3,1]$的值。
状态转移方程: $f[i,j] = min(f[i,j - 1],f[i + 2^{j-1},j - 1])$
初始状态为:$f[i,0] = data[i]$
求最值
已知待查询的区间$[x,y]$,求最值
我们把待查询的区间分成两个小区间,这两个小区间满足两个条件:
(1)这两个小区间要能覆盖整个区间
(2)为了利用预处理的结果,要求小区间长度相等且都为$2^i$。注意两个小区间可能重叠。
我们可以直接得到两段区间的$i=log_2^{l-r+1}$
把待查询区间$[x,y]$分成两个小区间$[x,x + 2^i - 1]$ 和 $[y - 2^i + 1,y]$,其又分别对应着$f[x,i]$和$f[y - 2^i + 1,i]$,此时为了求解整个区间的最小值,我们只需求这两个值得最小值即可,此时复杂度是$O(1)$。
下面给出完整的代码:
1 |
|