ST 算法

ST算法采用的是倍增的思想,先用O(nlogn)的时间构造一个二维表之后,可以在O(1)的时间查询[l,r]区间的最值
1.ST创建
 若F[i,j]表示[i,i+2^j-1]区间的最值,区间长度为2^j,则i和j的取值范围是多少呢?
 若数组的长度为n,最大区间长度2^(k)<=n<2^(k+1),则k=[log2(n)],比如n=8时k=3.
 在程序中,k=log2(n),也可用通用表达方式k=log(n)/log(2),log()表示以e为底的自然对数

算法代码:
 

void ST_create()//创建ST
{
    for(int i=1;i<=n;i++)//初始化
    {
        F[i][0]=a[i];//表示[i,i]区间的最值,区间长度为2^0
    }
    int k=log2(n);
    for(int j=1;j<=k;j++)
    {
        for(int i=1;i<=n-(1<<j)+1;i++)
        {
            F[i][j]=max(F[i][j-1],F[i+(1<<(j-1))][j-1]);
        }
    }
}

例如有10个元素a[1..10]={5,3,7,2,12,1,6,4,8,15},其查询最值的ST如下图所示。
F[i,j]表示[i,i+2^j-1]区间的最值,区间长队为2^j
F[1,0]表示[1,1+2^0-1]区间,即[1,1]的最值为5,第0列为数组自身
F[1,1]表示[1,1+2^1-1]区间,即[1,2]的最值为5
F[2,3]表示[2,2+2^3-1]区间,即[2,9]的最值为12
F[6,2]表示[6,6+2^2-1]区间,即[6,9]的最值为8

F[][] j    0   1   2     3
  i  1     5   5   7    12
     2       3   7  12   12
     3     7   7  12   15
     4     2  12 12
     5    12 12 12
     6     1   6   8
     7     6   6  15
     8     4   8
     9     8  15
    10   15

2.ST查询
  若查询[l,r]区间的最值,则首先计算k值,和前面的计算方法相同,区间长度为r-l+1,
  2^k<=r-l+1<2^(k+1),因此k=log2(r-l+1).
  若查询区间的长度大于或等于2^k且小于2^(k+1),则根据倍增的思想,可以将查询区分为两个查询区间
  取两个区间的最值即可。两个区间分别为从l向后的2^k个数及从r向前的2^k个数,这两个区间可能有重叠
  但对求最值没有影响。

int ST_query(int l,int r)
{
    int k=log2(r-l+1);
    return max(F[1][k],F[r-(1<<k)+1][k]);//取两个区间的最值
}

3.算法分析
  创建ST时,初始化需要O(n)时间,两个for循环需要O(nlogn)时间,总时间复杂度为O(n),
  区间查询实际上是查表的过程,复杂度为O(1)。一次建表多次使用,这种查表法就是动态规划

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值