RMQ算法

ST算法;

参考自:http://blog.csdn.net/sdj222555/article/details/7875575
主要是查询可以做到O(1),先预处理,用一个DP解决。
设a[i]是区间最值的数列,f[i,j]表示从第i个数起连续 2^j 个数中的最大值。
例如:
在数组:3 2 4 5 6 8 1 2 9 7,
f[1,0]表示从第1个数起,长度为2^0=1的最大值,也就3这个数,f[1,2]=5,f[1,3]=8,f[2,0]=2,f[2,1]=4……
而且从这里可以看出f[i,0]其实就等于a[i],已经有初始化了。
那么状态转移就是从小区间到大区间,类似一个区间DP吧。嗯,就是这样。

if(j + (1 << (i - 1)) <= n)
mx[j][i] = max(mx[j][i], mx[j + (1 << (i - 1))][i - 1]);
if(j + (1 << (i - 1)) <= n)
mi[j][i] = min(mi[j][i], mi[j + (1 << (i - 1))][i - 1]);

基于线段树的RMQ的结构;

在给定数列下,用O(logn)时间内实现
①求区间最小值
②修改某个位置的值
处理:线段树每个节点维护对应区间的最小值。在建树时,只需要按从下到上的顺序分别取左右儿子的值中的最小值就好了。

基于线段树的RMQ的查询;

如果要求a0,…,a6的最小值。我们只需要三个节点的值的最小就可以了。(这个在挑战书上的图里,下面有思路)
对于一个区间,我们去查询,线段树较上的节点对应较大的区间,通过这些区间就可以知道大部分的最小值,然后再去访问那些剩下的很少的节点就可以求得最小值了。
具体步骤:
1.如果要查询的区间和当前节点对应的区间完全没有交集,那么直接返回一个不影响答案的INF。
2.如果所查询区间完全包含当前节点所对应的区间,那么就返回当前节点的值。
3.以上两种情况都不满足,那只能说明:当前节点的区间完全包含了查询区间,或者说当前区间有些在被查询区间,有些不在查询区间。处理:对两个儿子进行递归处理,返回两个结果中的较小值。(这个处理自行画图会非常清楚)

基于线段树的RMQ的值的更新

在更新ai的过程中要让ai所在区间的对应的节点重新进行计算。
处理:可以从下面向上不断进行更新。(就是递归(DFS)嘛,你一直在满足条件的过程中搜到最底,然后只要在返回中取个较小值就好了啊)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值