倍增和稀疏表

本文深入探讨了倍增算法的概念,以及在ST(Sparse Table)构造和查询中的应用。ST表是一种高效解决在线区间最值查询(RMQ)问题的数据结构,通过预处理O(nlogn)时间复杂度,实现O(1)时间复杂度的查询。ST表创建与查询过程详细解析,对比线段树,突显ST在查询效率上的优势。此外,还介绍了RMQ问题的解决方法及其特点。
摘要由CSDN通过智能技术生成

倍增、STRMQ

1、倍增

任意整数均可被表示成若干个2的次幂项之和。例如:

  • 整数5,其二进制表示为101,该二进制数从右向左第0、2位均为1,则5=2+20

  • 整数26,其二进制表示为11010,该二进制数从右向左第1、3、4位均为1,则 26 = 2 4 + 2 3 + 2 1 26=2^4+2^3+2^1 26=24+23+21 。也就是说,2的次幂项可被拼成任一需要的值。

倍增,顾名思义就是成倍增加。若问题的状态空间特别大,则一步步递推的算法复杂度太高,可以通过倍增思想,只考察2的整数次幂位置,快速缩小求解范围,直到找到解。

2、ST

ST(Sparse Table,稀疏表)算法采用了倍增思想,在 O ( n l o g n ) O(nlogn) O(nlogn) 时间构造一个二维表之后,可以在 O ( 1 ) O(1) O(1) 时间在线查询 [ l , r ] [l, r] [l,r] 区间的最值,有效解决 在线RMQ(Range Minimum/Maximum Query,区间最值查询)问题。如何实现呢?

F [ i , j ] F[i,j] F[i,j] 表示 [ i , i + 2 j − 1 ] [i, i+2^j-1] [i,i+2j1] 区间的最值,区间长度为 2 j 2^j 2j

在这里插入图片描述

根据倍增思想,长度为 2 j 2^j 2j 的区间可被分成两个长度为 2 j − 1 2^{j-1} 2j1 的子区间,然后求两个子区间的最值即可。

递推公式: F [ i , j ] = m a x ( F [ i , j − 1 ] , F [ i + 2 j − 1 , j − 1 ] ) F[i,j]=max(F[i,j-1], F[i+2^{j-1},j-1]) F[i,j]=max(F[i,j1],F[i+2j1,j1])

在这里插入图片描述

2.1 ST表的创建

F [ i , j ] F[i, j] F[i,j] 表示 [ i , i + 2 j − 1 ] [i, i+2^{j}-1] [i,i+2j1] 区间的最值,区间长度为 2 j 2^j 2j,则和 j j j 的取值范围是多少呢?

若数组的长度为 n n n ,最大区间长度 2 k ≤ n < 2 k + 1 2^k≤n<2^{k+1} 2kn<2k+1,则 k = ⌊ l o g 2 n ⌋ k=\lfloor log_2n\rfloor k=log2n, 比如:

  • n=8时k=3,
  • n=10时k=3。

在程序中,k=log2(n), 也可用通用表达方式 k=log(n)/log(2)log()表 示以 e为底的自然对数。

void ST_create() {
	for(int i=1; i<=n; i++) {
		F[i][0]=a[i];// 区间[i,i]的最值,区间长度位2^0
	}
	int k=log(n)/log(2.0);
	for(int j=1; j<=k; j++) {
		for(int i=1; i<=n-(1<<y)+1; i++) {
			F[i][j]=max(F[i][j-1],F[i+(1<<j-1)][j-1])
		}
	}
}

例如,有10个元素 a [ 1..10 ] = 5 , 3 , 7 , 2 , 12 , 1 , 6 , 4 , 8 , 15 a[1..10]={5,3,7,2,12,1,6,4, 8,15} a[1..10]=5,3,7,2,12,1,6,4,8,15,创建查询最大值的ST表。 F [ i , j ] F[i,j] F[i,j] 表示 [ i , i + 2 j − 1 ] [i, i+2^j-1] [i,i+2j1] 区间的最值,区间长度为2。

在这里插入图片描述

2.2 ST表查询

若查询 [ l , r ] [l,r] [l,r] 区间的最值,则首先计算 k k k 值,和前面的计算方法相同,区间长度为 r − l + 1 r-l+1 rl+1 2 k ≤ r − l + 1 < 2 k + 1 2^k\leq r-l+1<2^{k+1} 2krl+1<2k+1, 因此 $k=log2(r-l+1) $。

若查询区间的长度大于或等于 2 2 2 且小于 2 k + 1 2^{k+1} 2k+1 ,则根据倍增思想,可以将查询区间分为两个查询区间,取两个区间的最值即可。两个区间分别为从向后的 2 k 2^k 2k 个数及从 r r r 向前的 2 k 2^k 2k 个数,这两个区间可能有重叠,但对求最值没有影响。

在这里插入图片描述

int ST_query(int l, int r){
	int k=log2(r-l+1);
	return max(F[l][k], F[r-(1<<k)+1][k])
}

3、RMQ

RMQ(区间最值查询)问题有多种解决方法,用线段树和ST解决RMQ问题的对比如下:

  • 线段树预处理的时间为 O ( n l o g n ) O(nlogn) O(nlogn),查询的时间为 O ( l o g n ) O(logn) O(logn) ,支持在线修改
  • ST预处理的时间为 O ( n l o g n ) O(nlogn) O(nlogn),查询的时间为 0 ( 1 ) 0(1) 0(1) ,不支持在线修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值