zoukankan      html  css  js  c++  java
  • 【算法#5】SparseTable

    Tarjan的SparseTable,即ST表,用于求RMQ区间最值问题。

    我对ST表的时间复杂度是有所疑惑的,我认为查询并不能够达到O(1)的速度。也许只是常数?但是查询区间长度为n的时候就要对长度进行logn次调整,蓝书上写的是这样,我不太确定。

    本质上,由于寻求区间最值的特性,在给定区间内多次覆盖是没有关系的,但是覆盖超过给定区间的操作是不合法的,所以我们建立一个数组储存从i点开始延伸(2^j)长度区间内的最小值。

    对于每个区间,一定有(2^k)大于该区间长度的一半,于是我们找到这个k并且用两个这样长度不同起点的数据覆盖区间即可。

    至于ST表的建立,递推方法是最简便的一种。首先,对于每个起点,j为零的时候其值为该点的值,然后对于j大于零,首先按j从小到大枚举,有:

    [st[i][j]=max(st[i][j-1],st[i+1<<j-1][j-1]) ]

    递推要注意边界,避免越界。

    板子贴在这里。

    void prepare(){
        for(int i=1;i<=n;i++)
            st[i][0]=a[i];
        for(int j=1;1<<j<=n;j++)
            for(int i=1;i-1+(1<<j)<=n;i++)
                st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
    }
    int result(int l,int r){
        int k=0;
        while(1<<k+1<=r-l+1)
            k++;
        return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    

    理论上不会有问题,有的话会来改正的。

    我就说吧,蓝书上的代码是有问题的。交上去之后TLE了,查询部分不是O(1)的,要考虑优化了。

    [doge],寻找合适的k那部分可以直接用STL的log2函数替代掉。修改过的代码应该是这样的:

    void prepare(){
        for(int i=1;i<=n;i++){
            cin>>a[i];
            st[i][0]=a[i];
        }
        for(int j=1;1<<j<=n;j++)
            for(int i=1;i-1+(1<<j)<=n;i++)
                st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
    }
    int result(int l,int r){
        int k=log2(r-l+1);
        return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    

    我****被输入卡了……我就说怎么特么的TLE关了同步的cin也要超时

    我觉得cin方便还不让我用了是吧……

  • 相关阅读:
    list中的对象或者map中的版本号排序 version排序
    spring boot jpa 复杂查询 动态查询 连接and和or 模糊查询 分页查询
    java 8 list的stream操作 list中的对象中的某一个成员取出转为该成员的list,以及对象过滤,筛选某个属性后的成员
    map或者对象转换
    Feign代理必须加value否则启动失败
    Eclipse中.setting目录下文件介绍
    远程仓库版本回退方法
    SpringMVC异常处理机制
    android studio启动和项目编译问题
    CentOS6.5安装php7+nginx+mysql实现安装WordPress
  • 原文地址:https://www.cnblogs.com/Schwarzkopf-Henkal/p/11830123.html
Copyright © 2011-2022 走看看