ST表学习

Posted song-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ST表学习相关的知识,希望对你有一定的参考价值。

 

不想解释,so推荐一个更好的网站

http://blog.csdn.net/insistgogo/article/details/9929103

http://www.cnblogs.com/zyf0163/p/4782133.html

总结:   用处:快速求解一个给定区间内的最值

  方法:ST算法分成两部分:离线预处理 (nlogn)和 在线查询(O(1))。虽然还可以使用线段树、树状链表等求解区间最值,但是ST算法要比它们更快,而且适用于在线查询。

  (1)离线预处理:运用DP思想,用于求解区间最值,并保存到一个二维数组中。

    状态转移方程是 F[i,j] = min(F[i,j - 1],F[i + 2^(j - 1),j - 1])

    初始状态为:F[i,0] = A[i]

  (2)在线查询:对给定区间进行分割,借助该二维数组求最值

  在程序计算求解区间长度时,并没有那么麻烦,我们可以直接得到i,即等于直接对区间长度取以2为底的对数。这里,对于区间[3,11],其分解的区间长度为int(log(11 - 3 + 1)) = 3,这里log是以2为底的。

  技术分享图片  

技术分享图片
#include <iostream>
#include <math.h>
using namespace std;

/*方程
F[i,j]:区间[i,i + 2^j - 1]的最小值,此时区间长度为2^j
F[i,j] = min(F[i,j - 1],F[i + 2^(j - 1),j - 1])
F[i,0] = nArr[i];*/

int F[1000000][20];//待比较元素的个数最大为1百万
void SparseTable(int nArr[],int nLen)
{
    //初始化
    for (int i = 0;i < nLen;i++)
    {
        F[i][0] = nArr[i];
    }
    //递推
    int nLog = int(log(double(nLen))/log(2.0));
    for (int j = 1;j <= nLog;j++)
    {
        for (int i = 0;i < nLen;i++)
        {
            if ((i + (1 << j) - 1) < nLen)//区间的端点不能超过数组最后一位的下标
            {
                F[i][j] = min(F[i][j - 1],F[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
}

int RMQ(int nArr[],int nLen,int nStart,int nEnd)
{
    int nLog = (int)(log(double(nEnd - nStart + 1)/log(2.0)));
    return min(F[nStart][nLog],F[nEnd - (1 << nLog) + 1][nLog]);
}

int main()
{
    int nArr[6] = {5,4,6,10,1,12};
    SparseTable(nArr,6);
     
    cout<<RMQ(nArr,6,0,5)<<endl;
    cout<<RMQ(nArr,6,1,3)<<endl;
    cout<<RMQ(nArr,6,2,5)<<endl;
    cout<<RMQ(nArr,6,2,2)<<endl;

    system("pause");
    return 1;
}
View Code

 

以上是关于ST表学习的主要内容,如果未能解决你的问题,请参考以下文章

19 01 11 javascript ?????????????????????(???????????????) ??????????????????????????????(代码片段

[新增ST-001片段]全程字幕-20套UML+Enterprise Architect建模示范视频

ds第七章学习记录

模板st表

《 常见算法与数据结构》符号表ST——二叉查找树 (附动画)

将数据从底部工作表对话框片段传递到片段