码迷,mamicode.com
首页 > 其他好文 > 详细

ST表学习

时间:2018-02-11 22:45:06      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:端点   iostream   2.0   等于   总结   blog   bubuko   bsp   lock   

 

不想解释,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表学习

标签:端点   iostream   2.0   等于   总结   blog   bubuko   bsp   lock   

原文地址:https://www.cnblogs.com/song-/p/8443157.html

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