RMQ区间最值查询SparseTable算法

//一维区间最值查询模板稀疏表sparse table算法
//区间最值查询--线段树--RMQ
//区间连续和--线段树
//区间第k大--快排--划分树(线段树?) --主席树 
//二维区间最值查询根据一维区间最值查询的思想写代码 
/*
区间最值查询RMP  ST 算法 
原理:  O(nlogn)预处理,O(1) 查询

        预处理--使用动态规划,令F(i,j)表示以i起始的2^j长的子序列
                F[i,0]即为原序列的每一个数,
                有状态转移方程F(i, j ) = max(F(i,j-1), F(i+ (1<<(j-1)) , j-1 )
        查询----对于i,j区间最值RMP(A,i,j) 
                他的长度为 j-i+1
                令k = log2( j - i + 1)
                有i~j区间的最值max(F(i,k) , F[j- (1<<k) + 1 , k ) )
复杂度  预处理 O(nlogn)
        查询   O(1)

应用    在线查询区间最值
*/ 

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

const int maxn = 1e5 + 10 ;

//F[i][j] 表示[i , i + ( 1<< j )- 1] 区间的最值 
int F[maxn][20 + 1] ;


void RMQ(int n ){
    //j必须在外循环, 因为状态转移方程是从j-1 到j , 也就是说要计算j,即必须计算完j-1的所有数 
    //j代表区间长度1<<j,他指的是[i, i + ( 1<< j ) -1 ] 的区间的区间长度是 1<< j  
    for ( int j = 1 ; j<= 20 ;j ++)
        //i代表区间起点i
        //区间[ i , i+ (1<<j) -1 ] 的最值为两部分区间[i , i + (1<<(j-1)) -1 ] 和[ i + (1<<(j-1)) , i + ( 1<<j) -1] 的最值 
        // F[i,j] = max( F[i , j-1] , F[i + (1<<(j-1)) +1 , j-1])  
        for(int i = 1 ; i <= n ;i ++)
            //保证第二个子区间下标在区间范围内 
            if( i + ( 1<<(j-1)) <= n )
                F[i ] [j]= max( F[i][j-1] , F[i + (1<<(j-1))] [ j -1] ) ; 
}
int query(int i , int j ){
    //划分区间长度让结果为两部分子区间的比较值
    //取子区间为前1<<k个数和后1<<k个数 
    int k = log10( j - i + 1.0) / log10 (2.0) ;
    return max( F[i][ k ] , F[j - ( 1<<k ) + 1] [ k]) ;
}

int main(){
    //n代表序列长度,m代表询问个数 
    int n , m ;
    cin>>n>>m ;
    for(int i = 1 ;i <= n ; i ++){
        cin>>F[i][0] ;
    }
    RMP( n ) ;
    while(m--){
        int i , j ;
        cin>>i >> j ;
        int ans = query( i , j) ;
        cout<<ans<<endl;
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值