ST表算法详解

 ST表算法详解

       关于ST表,有很多文章,这里本蒟蒻也来发一波~~ 希望能为您提供帮助~~

     ST表算法全称Sparse-Table算法,是由Tarjan提出的一种解决RMQ问题(区间最值)的强力算法。离线预处理时间复杂度 θ(nlogn),在线查询时间θ(1),可以说是一种非常高效的算法。不过ST表的应用场合也是有限的,它只能处理静态区间最值,不能维护动态的,也就是说不支持在预处理后对值进行修改。一旦修改,整张表便要重新计算,时间复杂度极高。动态最值可以用线段树、树状数组等来维护。

     ST表之所以广为使用,不仅因为它的时间复杂度优秀,还因为它的代码思路比较清晰,码量比较合适。核心的代码主要集中预处理和查询上。那么接下来我们就先来讲讲它的预处理(下面都以区间最小值来讲,最大值可以类推)。st[i][j]表示从第 i 个数起向后连续2^j个数中的最小值。注意,是包括第 i 个数在内的2^j个数。那么,我们可以得到转移方程:

     1.st[i][0]=第i个数(很明显,2^0==1,从第i个数起向后数1个数,当然只有它自己。)

     2.st[i][j]=min{ st[i][j-1] , st[i+(1<<j-1)][j-1]}(j≠0)(其实也挺好理解的。请看下图:                                

      (把整个2的j次方区间分成两个2^(j-1)区间,那么整个大区间的最小值就是两个已计算过的区间最小值的最小值。第一个区间很明白,是st[i][j-1],就是从左端点 i 起向右数2^(j-1) 个数。第二个区间长度还是2^(j-1),但是左端点需要由 i 加上上一个区间的长度,毕竟它们是连在一起的。)

    以上,就是ST表的初始化部分。

    接下来,我们来讲讲查询。假设每次查询的左右端点分别为le和ri。思路:首先找到一个值k,k的含义是“最大的2^k不超过查询区间长度(ri-le+1)”。举个例子:le=1,ri=9,那么k最大为3,2^k==8,不超过区间长度。那么我们找两个长度为2^k的区间,一个以le为左端点,一个以ri为右端点。由于k最大,所以可以肯定,这两个小区间一定覆盖了整个大区间。那么,虽然两个小区间会有重叠部分,但是这里要求的是最小值,而非求和,所以这两个小区间最小值中的最小值,一定是整个区间的最小值!

    再细一点的说,一个区间为st[le][k],还有一个为st[ri-(1<<k)+1][k],那么:

    查询函数query(le,ri)=min{st[le][k],st[ri-(1<<k)+1][k]}。再次强调:重叠的小区间不影响整个区间的最小值!

    再总结一下查询的过程:1.找到k    2.返回两个st之间的最值

    到这里,ST表的一般实现已被剖析完毕。下面为大家提供多次查询区间最小值的代码。

 

 1 #include<bits/stdc++.h>
 2 #define MX 100005
 3 using namespace std;
 4 int n,ans[(MX<<1)+MX<<3],st[MX][17];
 5 void getrd(){
 6     for(int j=1;(1<<j)<=n;j++)
 7         for(int i=1;i+(1<<j)-1<=n;i++)
 8             st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
 9 }
10 int query(int le,int ri){
11     int k=0;while(le+(1<<k+1)-1<=ri)k++;
12     return max(st[le][k],st[ri-(1<<k)+1][k]);
13 }
14 int main(){
15     int m;cin>>n>>m;
16     for(int i=1;i<=n;i++)cin>>st[i][0];
17     getrd();
18     for(int i=1;i<=m;i++){int le,ri;cin>>le>>ri;ans[i]=query(le,ri);}
19     for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
20     return 0;
21 }
View Code

   

    谢谢!这篇博客就到此结束了!希望对你有帮助!喜欢的话记得点赞哦~~

 

    

 

 

 

 

    

 

 

        

posted @ 2020-02-25 12:06  soul_maker  阅读(1419)  评论(0编辑  收藏  举报