• ST表(求解静态RMQ问题)


    例题:https://www.acwing.com/problem/content/1272/

    ST表类似于dp。

    定义st[i][j]表示以i为起点,长度位2^j的一段区间,即[ i , i + 2^j - 1 ]。

    而这个区间又可以被拆分为[i,i+2^(j-1)-1]+[ i + 2 ^ ( j - 1 ) , i + 2 ^ j - 1 ]这两个区间可以这样表示st[i][j-1]和st[i+(1<<(j-1))][j-1]

    所以

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

    然后枚举长度和端点就可以以O(nlogn)转移状态了。特别的st[i][0]=arr[i]

    查询:

    设查询区间为[x,y]。将[x,y]分为两个带有重叠的子区间即[x,k1]+[k2,y]。其中k1>=k2。

    怎样拆分呢?取log(y-x)向下取整,设为k,将[x,y]分为[x,x+2^k-1]+[y-2^k+1,y]。

    我们可以做一下差即y-2^k+1-x-2^k+1=y-x-2^(k+1)+2。 结果一定是小于等于0的。

    所以答案为:

    m(st[x][k],st[y-(1<<k)+1][k])

     例题code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1E5 + 7;
    int st[N][40];
    int n,m;
    int Log[N];
    int arr[N]; 
    void ST(){
    //    Log[1] = 0;//预处理log函数  
    //    for(int i = 2;i <= n+1;i++) Log[i] = Log[i/2]+1;
        for(int i = 1;i <= n;i++) st[i][0] = arr[i];
        
        for(int j = 1; (1<<j) <= n;j++){ 
            for(int i = 1;i + (1<<(j-1)) <= n;i++){
                st[i][j] = max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
            }
        }
    } 
    int main(){
        inint();
        ios::sync_with_stdio(0);
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>arr[i];
        ST(); 
        for(int i=1;i<=m;i++){
            int x,y;
            cin>>x>>y;
            int k= Log[y-x+1];
            cout<<max(st[x][k],st[y-(1<<k)+1][k])<<endl;
        }
        return 0;
    }

     记录一个求O(n)求log的方法

    log[i]=log[i/2]+1   当i刚好的i的倍数时,想当然log[i]=log[i/2]+1。

            当i不是i的倍数时,i/2刚好舍去余数,向下取整。。。秒~~

  • 相关阅读:
    Web应用程序使用Hibernate
    Hibernate使用注释
    Hibernate入门程序
    Hibernate体系结构
    Spring MVC文件上传教程
    Spring MVC配置静态资源和资源包教程
    Spring MVC4使用Servlet3 MultiPartConfigElement文件上传实例
    Spring4 MVC文件下载实例
    Spring4 MVC+Hibernate4 Many-to-many连接表+MySQL+Maven实例
    Spring4 MVC+Hibernate4+MySQL+Maven使用注解集成实例
  • 原文地址:https://www.cnblogs.com/Accepting/p/12577784.html
Copyright © 2020-2023  润新知