数据结构---Sparse Table 稀疏表

Sparse Table(ST表)

ST表是解决 RMQ (Range Minimum/Maximum Query) 静态区间最值查询问题的离线数据结构。其预处理时间复杂度为 O(nlogn) ,查询时间复杂度为 O(1),n为序列长度。RMQ 问题也可以用线段树来解决,只不过线段树的查询复杂度为 O(nlogn) 而且代码量大。
本文以求最小值为例。

算法

  1. 算法利用了二分和动态规划的思想:

设 st[i][j] 表示区间 [i,i+2^j-1] 内的最小值。
例:对于序列 3,2,4,5,6,8,1,2,9,7
则:st[1][0]=3,st[1][1]=2,st[1][2]=2,st[1][3]=1 。
也就是第 i 个数起,连续 2^j 个数中的最小值。

  1. st[i][j] 的转移方程:

st[i][j] = min( st[i][j-1] ,st[i+(1<<(j-1))][j-1] )
注意其中 j 是阶段,i 是状态,所以循环中 j 放在外层。

void init_ST()
{
	for(int j=1;j<=floor(log(n)/log(2));j++)
	    for(int i=1;i+(1<

预先需要令 st[i][0]=a[i] 。 a[] 是原序列,这个式子同样符合 st 的定义。

  1. 查询

查询时,用两个长度为 2^ k 的区间覆盖待查询区间,而长度为 2^ k 的区间最值可以直接从 st数组 中得到
其中 k = floor(log(b-a+1)/log(2))
即 2^k = b-a+1 向下取整。
区间 [a,b] 的最小值为 min(st[a][k],st[b-2^k+1][k])

init_ST();
for(int i=1;i<=M;i++)
{
	int a, b, k, ans;
	scanf("%d%d", &a, &b);       //输入查询区间
	k = floor(log(b-a+1)/log(2));
	ans = min(ST[a][k], ST[b-(1<

例题

模板: 洛谷P3865 【模板】ST表.
另一个模板,我自己用线段树做了一遍:洛谷P2880 [USACO07JAN]Balanced Lineup G.

你可能感兴趣的:(数据结构)