【算法#5】SparseTable

余生颓废 提交于 2019-12-04 04:07:06

Tarjan的SparseTable,即ST表,用于求RMQ区间最值问题。

我对ST表的时间复杂度是有所疑惑的,我认为查询并不能够达到O(1)的速度。也许只是常数?但是查询区间长度为n的时候就要对长度进行logn次调整,蓝书上写的是这样,我不太确定。

本质上,由于寻求区间最值的特性,在给定区间内多次覆盖是没有关系的,但是覆盖超过给定区间的操作是不合法的,所以我们建立一个数组储存从i点开始延伸\(2^j\)长度区间内的最小值。

对于每个区间,一定有\(2^k\)大于该区间长度的一半,于是我们找到这个k并且用两个这样长度不同起点的数据覆盖区间即可。

至于ST表的建立,递推方法是最简便的一种。首先,对于每个起点,j为零的时候其值为该点的值,然后对于j大于零,首先按j从小到大枚举,有:
\[\text{st[i][j]=max(st[i][j-1],st[i+1<<j-1][j-1])}\]

递推要注意边界,避免越界。

板子贴在这里。

void prepare(){
    for(int i=1;i<=n;i++)
        st[i][0]=a[i];
    for(int j=1;1<<j<=n;j++)
        for(int i=1;i-1+(1<<j)<=n;i++)
            st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
int result(int l,int r){
    int k=0;
    while(1<<k+1<=r-l+1)
        k++;
    return max(st[l][k],st[r-(1<<k)+1][k]);
}

理论上不会有问题,有的话会来改正的。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!