打印
[其他ST产品]

ST表——解决区间最值问题的好帮手

[复制链接]
265|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

多余的文字就不多赘述了,直接上代码,边看边解释。(这小编也太烂了吧,算了,将就将就吧)


#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

/*
建表时间o(nlogn),查询时间o(1)
不支持在线更新
*/
class ST
{
private:
    int dp[10000][30]; //dp[i][j]表示从第i个元素开始,长度为2的j次方这个区间的的最值
    void build(int nums[],int len)
    {
        //先初始化长度为1的最值,以后长度为2,4,8....
        for(int i=1;i<=len;i++) dp[i][0]=nums[i-1]; //以i为开头,长度为1的区间的最值

        int k=(int)(log(len*1.0)/log(2.0));

        //2^k<=len<2^(k+1)
        for(int j=1;j<=k;j++) //每次区间的长度设计为2的j次方
        {
            for(int i=1;i<=len-(1<<j)+1;i++) //i+length => i+(1<<j)-1<=n
            {
                dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
            }
        }
    }

public:
    ST(int nums[],int len)
    {
        build(nums,len);
    }

    int query(int left,int right)
    {
        left++,right++;  //满足从下标0开始检索

        int k=(int)(log(right-left+1)/log(2.0));

        //2^k<=right-left+1<2^(k+1)
        //所以从left开始向右覆盖一个长度为2^k区间,和从right向左覆盖一个
        //长度为2^k的一个区间一定会覆盖完整个left到right区间,可能会有重叠
        //但是一定不会超过[left,right]区间,所以对答案无影响
        return max(dp[left][k],dp[right-(1<<k)+1][k]);
    }
};


int main()
{
    int len=8;
    int nums[]={3,5,1,10,7,9,3,2};


    ST my_st=ST(nums,len);

    cout<<my_st.query(0,7);

    return 0;
}

还是比较简单易懂的吧。


  • #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;

    /*
    建表时间o(nlogn),查询时间o(1)
    不支持在线更新
    */
    class ST
    {
    private:
        int dp[10000][30]; //dp[i][j]表示从第i个元素开始,长度为2的j次方这个区间的的最值
        void build(int nums[],int len)
        {
            //先初始化长度为1的最值,以后长度为2,4,8....
            for(int i=1;i<=len;i++) dp[i][0]=nums[i-1]; //以i为开头,长度为1的区间的最值

            int k=(int)(log(len*1.0)/log(2.0));

            //2^k<=len<2^(k+1)
            for(int j=1;j<=k;j++) //每次区间的长度设计为2的j次方
            {
                for(int i=1;i<=len-(1<<j)+1;i++) //i+length => i+(1<<j)-1<=n
                {
                    dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
                }
            }
        }

    public:
        ST(int nums[],int len)
        {
            build(nums,len);
        }

        int query(int left,int right)
        {
            left++,right++;  //满足从下标0开始检索

            int k=(int)(log(right-left+1)/log(2.0));

            //2^k<=right-left+1<2^(k+1)
            //所以从left开始向右覆盖一个长度为2^k区间,和从right向左覆盖一个
            //长度为2^k的一个区间一定会覆盖完整个left到right区间,可能会有重叠
            //但是一定不会超过[left,right]区间,所以对答案无影响
            return max(dp[left][k],dp[right-(1<<k)+1][k]);
        }
    };


    int main()
    {
        int len=8;
        int nums[]={3,5,1,10,7,9,3,2};


        ST my_st=ST(nums,len);

        cout<<my_st.query(0,7);

        return 0;
    }




使用特权

评论回复
沙发
yangxiaor520| | 2023-4-23 17:00 | 只看该作者
确实有点懒,一来就是代码。

使用特权

评论回复
板凳
Pretext| | 2023-4-23 19:05 | 只看该作者
代码有注释就行,纯代码还得自己去读,麻烦的。

使用特权

评论回复
地板
天天向善| | 2023-4-23 19:05 | 只看该作者
不知道效率怎么样,这种数据处理比较讲究效率问题。

使用特权

评论回复
5
芯路例程| | 2023-4-23 19:06 | 只看该作者
cpp呀,能不能用到ST上面哦。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

631

帖子

0

粉丝