ST(稀疏表):
Sparse Table is a data structure that answers static Range Minimum Query (RMQ). It is recognized for its relatively fast query and short implementation compared to other data structures.
它是对于静态数据快速查询任意区间最值问题的一种数据结构,数据是静态的,不能修改.
ST一般处理两种问题:
ST表使用的情景:
RMQ问题,一般暴力的求一个区间的最值问题,时间复杂度是O(n),单次的查询还可以接受,但是多次需要查询不同的区间的最值,在这个查询里面就要消耗O(n)的时间复杂度,有时候是不能接受的,比如在竞赛里面,那么就是使用ST表了,ST表查询区间的最值的时间复杂度是O(1)
哈哈,前面说了这么多,都是说它有多好,下面正式进入主题,以一个例子说一下
我们有一个数据: 3 1 2 5 4 ,将它放在数组arr中
现在我们需要查询出这个数据的任意一个区间的最大值,使用ST算法进行解决
我们先构造一个ST表,就是一个二维数组,数组的大小为[n][log(n)],n是数据的个数
结果如下图所示
解释一下ST表的含义,s[i][j]代表的是从第i个数据开始,2 ^ j个数字的区间中的最大值,就是数组arr的[i,i+2 ^ j-1]区间的最大值,
根据表的规律,可以得出ST表的初始化公式:s[i][j]=max(s[i][j-1],s[i+1<<(j-1)][j-1])
这个公式也好理解,ST表的行i表示从第i个数开始的区间,列j表示这个区间里面有2 ^ j个数,
要求s[i][j]的值,就是区间[i,i+2 ^ j] 的最大值,
这个区间的最大值不就是 s[ i ][ j-1] (区间[i,i+2 ^ (j-1) -1] 最大值)和
s[i+1<<(j-1)][j-1] (区间[i+2 ^(j-1), i+ 2 ^ j -1]最大值) 这两个数中最大的一个吗?
就是将这个大的区间分成两个小区间的,得到两个小区间的最大值,再在两个值中选择最大的那个,就是这段区间的最大值了
所以ST表后面的状态是继承前面的状态的
前面都是预处理,将ST创建好后,接下来就是查询区间的最大值
我先给出查询的公式再解释
这个公式应该怎么理解呢?这样的,先明确一下我们的目的,求这个区间的最大值,现在假设是求这五个数据的最大值,我们又要是使用ST表的,但是ST表没有直接存储从第一个元素开始,第五个元素结束的最大值,ST表存储的都是2的次方个数据的区间的最大值
那么我们就想将这个区间分成两部分,而且是两部分的区间的最大值能在ST表里面找到最大值,(这两个区间可能重叠,也可能不重叠,像现在的例子就重叠了)
那现在的问题就是我们要怎么分
我们发现,2 ^ (int)(log(len)) 的值是在len/2到len之间的(这里的len只是表示一个数)
因为 2 ^(log(len)就是len,但是 (int)(log(len)就是将小数点去除了,
但是2 ^ (int)(log(len)) 肯定比len/2大,因为len/2是(log(len)少了一个1
发现这个就好了,我们将区间分成两部分,
前面是:s[left][len] ,这个好理解
后面是:s[right-(1<<len)+1][len]
这个的len也好理解,有人可能想right-(1<<len)+1怎么来的?
就是从后面开始计算,这个小区间有1<<len个数,就是index +(1<<len)-1=right
所以index=right -(1<<len)+1
两个区间加起来就是大的区间,因为这两个区间要么各自就是大区间的一半,要么就是大于大区间的一半
这样子就可以使用O(1)的时间复杂度来查询区间的最大值,应该也说完了(不知道有没有说清楚了,哈哈)