ST表的学习

作用

ST表的优势在于可以把查询一个区间的最值的时间复杂度降为 O ( 1 ) O(1) O(1)

状态转移

假设有一个数组里有10000个元素,第i个元素记为ar[i]。
我们用f[i][j]表示从第i个元素开始,向右i+2j-1的 这些元素的最大值。
有f[i][j]=max(f[i][j-1],f[i+2j-1][j-1])
这其实是把区间[i][j]分成了两个部分,每部分的长度均为2j-1,将两个部分的最大值保存在f[i][j]中。有了这个状态转移方程后,就可以求出所有的f数组了。不难看出,时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

	for (j = 1; j <= lg[n]; j++)
	{
		for (i=1;(i+(1<<(j-1)))<=n;i++)
		{
			f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
		}
	}

如何查询

这里的思想非常巧妙。设查询的区间为[L][R]
则查询区间的长度为len=R-L+1
查询结果为max(f[L][ l o g ( l e n ) log(len) log(len)],f[R-2len+1][ l o g ( l e n ) log(len) log(len)]
通过两次分别向左,向右的查询,可以巧妙的覆盖整个查询区间。由于 l o g log log经常需要调用,需要预处理一下。
l g [ i ] = l g [ i / 2 ] + 1 lg[i]=lg[i/2]+1 lg[i]=lg[i/2]+1
用代码实现的话,就是

	while (q--)
	{
		int l, r, len,ans;
		scanf("%d%d", &l, &r);
		len = r - l + 1;
		ans = max(f[l][lg[len]], f[r - (1 << lg[len]) + 1][lg[len]]);
		printf("%d\n", ans);
	}

这样,通过预处理 O ( n l o g n ) O(nlogn) O(nlogn)后,每次查询的时间复杂度仅为 O ( 1 ) O(1) O(1)。是不是很快呢?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值