ST(稀疏表),RMQ的另一种实现方式

相关链接:

ST:  Sparse Table

RMQ:RMQ

RMQ的两种实现方式:

一、线段树

二、稀疏表(ST)

平均时间复杂度:O(N*LogN) 

如果不进行修改操作的话,ST的效率会更高。

ST的计算步骤: 

一、DP计算ST

二、以O(1)查询(L,R)的最值 

 code:

int a[maxn],dp[maxn][30],n;//之前有笔误,dp的列数最多只有log2(maxn),在这里,我就写成30
//建立稀疏表
void st(int n)
{
	for(int i=1;i<=n;++i)
		dp[i][0]=a[i];
	for(int j=1;(1<<j)<=n;++j) //之前的笔误,实际上是要保证i+2^j-1<=n还要保证2^j<=n
		for(int i=1;i+(1<<j)-1;++i)
			dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);//状态转移方程,注意优先级的问题,1+(j-1)要加上括号,否则会莫名其妙地出现问题
}
//O(1)的查询操作
int rmq(int l,int r)
{
	int k=0;
	while(1<<(k+1)<=(r-l+1))	k++;
	return max(dp[l][k],dp[r-(1<<k)+1][k]);
}

一些解释:

1.dp[i][j]的定义 ,dp[i][j] => (i,i+2^j-1)

2.a[i]表示原数列。 

2.状态转移方程为什么是这样?

dp[i][j] => (i,i+2^j-1) \Rightarrow \left\{\begin{matrix} dp[i][j-1] \Rightarrow (i,i+2^{j-1}-1) <1> \\ dp[i+(1<<(j-1))][j-1] \Rightarrow (i+2^{j-1},i+2^j-1) <2>\end{matrix}\right.    

3.对于<2>的解释:       

dp[i+(1<<(j-1))][j-1] \Rightarrow i+2^{j-1}-1+2^{j-1} = i + 2^j-1 \Rightarrow (i+2^{j-1},i+2^j-1)

4.到这里,聪明的读者一定已经完全掌握了DP计算ST;

5.现在,我们来看我们的查询函数RMQ为什么是这样子的:

首先,让我们假设我们要查询的区间是(L,R),

所以,区间的长度就是:R-L+1,但是根据我们构造的ST,可能没有一个区间是对应我们要查询的区间的。

也就说:(R-L+1)  Mod 2  ! = 0

因此,我们就要把要查询的区间分成两个部分:(L,R) \Rightarrow \left\{\begin{matrix} (L,R')\\ (L',R) \end{matrix}\right.

而且,这两个部分的长度都必须是可以直接查询的。

接下来,我们该如何计算 : L' , R' 呢?

define   K:

K = FLOOR(log_{2} (R-L+1))

易得:2^{K} <= R

同理:L >= R - 2^{K} + 1

所以令:

R' = K

L' = R-2^K +1

举个例子:

原数列:{1,2,3,4,5}

现在要查询:(1,5)的最大值

L = 1,R' =4 \Rightarrow (1,4) : 1\2\3\4 \Rightarrow MAX<1>= 4

L' = 2,R=5 \to \Rightarrow (2,5) : 2\3\4\5 \to \Rightarrow MAX<2> =5

之后我们比较大小: (L,R) = MAX((L',R),(L,R'))\Rightarrow MAX(4,5)\Rightarrow MAX=5

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值