st表学习笔记

1. ST表

1.1. 功能

RMQ(Range Maximum/Minimum Query)
也就是查询区间的最值
注意:
1、只能查,不能修改
2、只能RMQ,不能区间和

1.2. 原理:动态规划,倍增

1.3. 操作

1.3.1. 建表

1.3.1.1. 定义:

st[i][j]表示数组a[n]中以 i i i左端点长度为 2 j 2^j 2j 的区间
考虑用动态规划实现

1.3.1.2. 转移方程

对于长度大于 1 1 1的区间 [ l , r ] [l,r] [l,r],都有
令 m = [ l + r 2 ] 则 [ l , r ] 最小值 = min ⁡ ( [ l , m ] 最小值 , [ m + 1 , r ] 最小值 ) 令m=[\frac{l+r}{2}]\\ 则[l,r]_{最小值}= \min([l,m]_{最小值}, [m+1,r]_{最小值}) m=[2l+r][l,r]最小值=min([l,m]最小值,[m+1,r]最小值)

   l           r    [l,r]最小值=3
   |           |
...3 5 4 9 8 5 6...
   |     | |   |    [l,m]最小值=3
   l     m m+1 r    [m+1,r]最小值=5

                    3=min(3,5)

对于st[i][j],易知
l = i r = i + 2 j − 1 m = [ l + r 2 ] = [ 2 i + 2 j − 1 2 ] = i + 2 j − 1 − 1 l=i\\ r=i+2^j-1\\ m=[\frac{l+r}{2}] =[\frac{2i+2^j-1}2] =i+2^{j-1}-1 l=ir=i+2j1m=[2l+r]=[22i+2j1]=i+2j11
故有
s t [ i ] [ j ] = min ⁡ ( s t [ i ] [ j − 1 ] , s t [ i + 2 j − 1 ] [ j − 1 ] ) st[i][j]= \min(st[i][j-1],st[i+2^{j-1}][j-1]) st[i][j]=min(st[i][j1],st[i+2j1][j1])
递推顺序:
由于算长度为 2 j 2^j 2j的区间要用到长度为 2 j − 1 2^{j-1} 2j1的区间,故外侧循环j从小到大,内层循环i遍历区间

1.3.1.3. 边界条件

j = 0 j=0 j=0时, 2 j = 1 2^j=1 2j=1,区间长度为 1 1 1,故
s t [ i ] [ 0 ] = a [ i ] st[i][0]=a[i] st[i][0]=a[i]

1.3.1.4. 复杂度

时间复杂度:
初始化, O ( n ) O(n) O(n)
递推, O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
故总体 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

空间复杂度:
st[i][j] i ∈ [ 0 , n − 1 ] i\in[0,n-1] i[0,n1] j ∈ [ 0 , [ l o g 2 n ] ] j\in[0,[log_2n]] j[0,[log2n]]
故复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

1.3.2. 查询

查询a的区间 [ l , r ] [l,r] [l,r]的最小值
区间长度 l e n = r − l + 1 len=r-l+1 len=rl+1
j = [ l o g 2 l e n ] j=[log_2len] j=[log2len]

∵ j ≤ l o g 2 l e n ∴ 2 j ≤ 2 l o g 2 l e n = l e n ∵ j + 1 > l o g 2 l e n ∴ 2 j + 1 > 2 l o g 2 l e n 2 j > l e n 2 综上, l e n 2 < 2 j ≤ l e n \because j \le log_2len \\ \therefore 2^j \le 2^{log_2len}=len \\ \because j+1>log_2len \\ \therefore 2^{j+1}>2^{log_2len} \\ 2^j >\frac{len}2 \\ 综上,\frac{len}2<2^j \le len jlog2len2j2log2len=lenj+1>log2len2j+1>2log2len2j>2len综上,2len<2jlen
因此,区间 [ l , l + 2 j − 1 ] ∪ [ r − 2 j + 1 , r ] [l,l+2^j-1]\cup[r-2^j+1,r] [l,l+2j1][r2j+1,r]就是区间 [ l , r ] [l,r] [l,r]

...3 5 4 9 8 5 6...
   |     |     |
   l     m     r   min=3

   3 5 4 9
   |     |
   l     l+2^j-1   min=3

         9 8 5 6
         |     |
       r-2^j+1 r   min=5
3=min(3,5)

A ∪ B = C A\cup B=C AB=C,则 m i n ( m i n ( A i ) , m i n ( B i ) ) = m i n ( C i ) min(min(A_i),min(B_i))=min(C_i) min(min(Ai),min(Bi))=min(Ci)
(另外,区间和没有该性质,故st表不能解决区间和问题)

C _________________
A ___________
B       ___________

因此,要求的区间 [ l , r ] [l,r] [l,r]的最小值就是求
min(
区间 [ l , l + 2 j − 1 ] [l,l+2^j-1] [l,l+2j1]的最小值,
区间 [ r − 2 j + 1 , r ] [r-2^j+1,r] [r2j+1,r]的最小值
)
而以上两个区间长度都是 2 k ( k ∈ N ∗ ) 2^k(k\in N*) 2k(kN),故可以直接查st获取最小值,时间复杂度 O ( 1 ) O(1) O(1)

1.4. 实现

//2^x
inline int pw2(int x){
    return 1<<x;
}

int st[N][LOG_N];
int log2[N];

//初始化
inline void init(){
    //计算log2
    for(int i=1,x=0;i<=n;i++){
        if(i==(1<<(x+1))){
            x++;
        }
        log2[i]=x;
    }
    //边界条件
    for(int i=0;i<n;i++){
        st[i][0]=a[i];
    }
    //递推
    for(int i=1,x=1;i<=log2[n];i++,x<<=1){
        //x=2^(i-1)
        int l=0,m=l+x-1,r=m+x;
        while(r<n){
            st[l][i]=min(st[l][i-1],st[mid+1][i-1]);

            l++;m++;r++;
        }
    }
}

//查询
inline int query(int l,int r){
    int j=log2[r-l+1];
    return min(st[l][j],st[r-pw2(j)+1][j]);
}
  • 46
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值