关于基础RMQ——ST算法
2022-05-27 11:38
1076 查看
RMQ,Range Maximum/Minimum Query,顾名思义,就是询问某个区间内的最大值或最小值,今天我主要记录的是其求解方法——ST算法
相对于线段树,它的运行速度会快很多,可以做到O(log n)的预处理和O(1)的查询,不足就是无法进行区间修改,这个一会就会提及
我将从四个方面进行记录:
1、ST的算法流程
其实与DP有很大的相似性,用 a[1,2,....,n] 来记录整组数据,设 f[i,j] 代表从 a[i] 到 a[i+ -1] 之间所有元素的最大值。
不难发现,其实这个区间就有 个元素。现在我们将这些元素平均分为两部分,那么每部分就是 个元素,而这两个集合就可以写成:
那么整个区间的最大值就转换成了两个区间最大值的较大值,根据动态规划的最优化原理,就可以轻松的写出状态转移方程:
边界条件就是:
2、询问
要想要找出区间 [x,y] 的最大值,与刚才讲的方法类似,找出最大的 a 满足:
至于为啥不能是直接取等于,是因为取等于时不一定是整数。
所以 不一定是正好是整个区间的一半,会出现以下这种情况:
不过That's OK,因为就算区间有重叠也不会影响最大值的确定,但是如果进行区间的操作的话可能就不适用了,因为重叠的部分会被操作两次,这明显不公平!这也是我最开始的时候对ST进行批判的原因,也是ST算法只适用于求区间最值的原因。
3、代码实现
刚才其实都讲的差不多了,不做过多解释:
#include<cstdio> #include<cmath> #include<iostream> #include<algorithm> using namespace std; const int NN=1e6+5; int f[NN][21];//21位就差不多了,2的21次方超过了1e6 inline int read()//快读 { char ha=getchar(); int x=0,sign=1; while(ha<'0'||ha>'9') { if(ha=='-') { sign=-1; } ha=getchar(); } while(ha>='0'&&ha<='9') { x=x*10+ha-'0'; ha=getchar(); } return x*sign; } int Query(int l,int r) { int logg=log2(r-l+1); int haha=max(f[l][logg],f[r-(1<<logg)+1][logg]); return haha; } int main() { int N=read(),M=read(); for(int i=1;i<=N;i++)//初始化,只有一个数的区间最大值就是它本身 { f[i][0]=read(); } for(int j=1;j<=21;j++)//开始DP找最大值 { for(int i=1;i+(1<<j)-1<=N;i++) { f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } for(int i=1;i<=M;i++) { int l=read(),r=read(); int ans=Query(l,r); printf("%d\n",ans); } return 0; }
四、例题精讲
敬请期待!
To Be Continued...
相关文章推荐
- 算法基础 - RMQ-ST算法(在线算法)
- 关于结对编程的问题——零基础新人
- 关于Java基础的复习总结(四)初识面向对象
- 关于c++头文件的基础知识
- C基础--关于typedef的用法总结
- 关于对于spring当中一些基础概念的理解
- 关于一些基础概念的复习和总结
- 关于git基础操作
- 关于多线程的基础知识和小示例
- oracle 关于ID自增和在原有ID的基础上自增
- 关于iOS基础总结(4)--动画、MVVM、图片缓存、常用第三方
- 关于学习NDK基础知识这些就够了(三)
- 基础中的基础,关于网页DOCTYPE(文档类型)的定义
- 七十八、基础框架(三十六)内存管理-关于内存管理规则的概括
- 关于RMQ问题的一些感悟
- vc6.0 关于“microsoft 基础类应用程序 已停止工作” 解决方案
- Java基础-关于session的详细解释
- 关于iOS基础总结(6)--无线轮播
- salesforce 零基础学习(三十一)关于LookUp字段点击Save时的Validation
- 关于单片机的C语言编程基础知识(初学注意)