码迷,mamicode.com
首页 > 编程语言 > 详细

RMQ问题 ST算法

时间:2018-11-02 23:44:17      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:pre   表达式   方法   lin   之一   原因   流程   str   strong   

RMQ是询问某个区间的最大值或最小值的问题,主要求解方法之一ST算法;

ST算法其实是倍增思想的产物,等下看代码实现就很明显了

ST算法通常用在要多次询问一些区间的最值的问题中,相比于线段树,它的程序实现更简单,运行速度更快;

ST算法没有修改操作(或者说不擅长动态修改)

ST算法流程:

预处理:ST算法的原理实际上是动态规划,我们用a数组表示一组数,设\(f[i,j]\)表示从\(a[i]\)\(a[i+2^j-1]\)这个范围内的最大值,从中间平均分成两部分,即把\(f[i,j]\)分为\(f[i,j-1]\)\(f[i+2^{j-1},j-1]\)(是不是很像倍增!!!)

整个区间的最大值一定是左右两部分最大值的较大值,于是得到状态转移方程:

\(f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])\)

边界条件为\(f[i][0]=a[i]\);

于是我们可以预处理出f数组;

询问:若询问区间\([l,r]\)的最大值,则先求出最大的x满足\(2^x<=r-l+1\),那么区间

\([l,r]=[l,l+2^x-1]∪[r-2^x+1,r]\)

两个区间有并集,但不妨碍求区间最值,这也是ST算法只能求区间最值的原因;

求区间\([x,y]\)的最大值,表达式为:

\(k=log_2(y-x+1)\);

\(ans=max(f[x][k],f[y-2^k+1][k])\);

因为log函数效率不高,通常递推预处理k值(设\(log[d]\)表示\(log_2\)d向下取整,取\(log[d]=log[d/2]+1\)):


log[0]=-1;//log[0]=-1,才能使log[1]=0
for(int i=1;i<=n;i++)
    log[i]=log[i>>1]+1;
    

模板:


log[0]=-1;
for(int i=1;i<=n;i++)//n个数的序列
    f[i][0]=a[i],log[i]=log[i>>1]+1;
//f[i][0]表示从i下标开始的2^0个数字的最大值是本身
//预处理处长度为1~n的log数组
for(int j=1;j<=LogN;j++)
//LogN一般取20即可
for(int i=1;i+(1<<j)-1<=n;i++)
//1<<j即2^j
    f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1])
while(m--){
    cin>>x>>y;//询问区间[x,y]内的最大值
    int k=log[y-x+1];//log2(y-x+1)向下取整的值
    cout<<max(f[x][k],f[y-(1<<k)+1][k]);
}

RMQ问题 ST算法

标签:pre   表达式   方法   lin   之一   原因   流程   str   strong   

原文地址:https://www.cnblogs.com/PPXppx/p/9898584.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!