RMQ笔记(Sparse Table算法实现,也就是ST算法)

引入一个大小为size(以size=5为例)的数组:[ 2, 5 , 3 , 7 , 6]

对于查询区间[l,r],如何快速得到区间最小值呢?
分析:如果直接用dp[i][j]表示第i个数到第j个数(含两端)的最小值,一般size比较小可以这样做
状态转移方程: d p [ i ] [ j ] = m i n ( d p [ i ] [ k ] , d p [ k ] [ j ] ) , i ≤ k ≤ j dp[i][j]=min(dp[i][k],dp[k][j]), i\leq k \leq j dp[i][j]=min(dp[i][k],dp[k][j]),ikj
一般题目的size范围都会有1e5,开这么的二维数组肯定会炸内存的,而RMQ就比较好的解决了这个问题


RMQ首先将dp[i][j]的含义改成从第i个数开始连续 2 j 2^j 2j个数的区间内的最小值,这样由于将dp数组的第二维取以2为底的对数,从而使在int范围内都不会炸内存,但是这也带来一个为题,就是
d p [ i ] [ j ] , j = 0 , , 1 , 2 , ⋯ 能   直 接   查 询 的 区 间 只 有 从 第 i 个 数 开 始 连 续 的 2 0 , 2 1 , 2 2 , ⋯ 个 数 的 区 间 dp[i][j],j=0,,1,2,\cdots \\ 能 \ 直接 \ 查询的区间只有从第i个数开始连续的2^0,2^1,2^2 ,\cdots 个数的区间 dp[i][j],j=0,,1,2,  i20,21,22,
状态转移方程: ( 将 2 j 大 小 的 区 间 分 成 两 个 2 j − 1 大 小 的 区 间 ) (将2^j大小的区间分成两个2^{j-1}大小的区间) (2j2j1)
d p [ i ] [ j ] = m i n ( d p [ i ] [ j − 1 ] , d p [ i + ( 1 &lt; &lt; ( j − 1 ) ) ] [ j − 1 ] ) dp[i][j]=min(dp[i][j-1],dp[i+(1&lt;&lt;(j-1))][j-1]) dp[i][j]=min(dp[i][j1],dp[i+(1<<(j1))][j1])
可以发现dp[i][j]的更新都是在dp[i][j-1]的基础上更新的,因此预处理的时候j应先小后大
预处理代码:

void RMQ_init()
{
   
	for(int i=1;i<=n;i++)
		dp[i][0]=arr[i];
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i+(1<<j)-1<=n;i++)
			dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}

而 对 于 从 第 i 个 数 开 始 的 连 续 的 3 个 数 , 5 个 数 , 6 个 数 , 7 个 数 , 9 个 数 , ⋯ 这 些 数 的 区 间 都 不 能 直 接 查 询 得 到 而对于从第i个数开始的连续的3个数,5个数,6个数,7个数,9个数,\cdots这些数的区间都不能直接查询得到 i3,5,6,7,9,
解决方法:
    其实对于查询区间的大小为M的查询区间[l,r],只要找出两个区间(大小分别为 2 a , 2 b 2^a,2^b 2a,2b),并且这两个区间合区间必须等于查询区间[l,r](也就是说这两个区间可以在l,r的中间有重叠 ),最终结果就是将这两个区间取个最小值
因此RMQ在查询上按照上面的思路进行了处理,首先令 k = l o g 2 ( r − l + 1 ) k=log_2(r-l+1) k=log2(rl+1),那么2^k有可能比查询区间的大小略小,然后RMQ就简单粗暴地将这两个区间的大小都改为 2 k 2^k 2k的大小(即a=b=k)
(对于这两个区间只要它们覆盖查询区间[l,r]就行,至于大小,当然是怎样查起来方便就开多少,因此RMQ就直接开 2 k 2^k 2k大,因为开这么大比较好处理呀,下面就会知道为啥子了)。
现在要解决的问题就是确定这两个区间的起始位置,并且它们的合区间必须得是 [ l , r ] [l,r]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值