RMQ的两种实现方法
来源:互联网 发布:培训机构网站源码 编辑:程序博客网 时间:2024/06/05 15:43
- 引言
- 线段树实现RMQ
- 主要思路
- 代码实现
- 时间复杂度
- ST表实现RMQ
- 主要思路
- 代码实现
- 时间复杂度
引言
RMQ算法(Range Minimum/Maximum Query) 是求区间极值的高效算法,依据所需实现的不同性能可以有多种写法,这里主要讲基于线段树和稀疏表(Sparse Table)的两种方法
线段树实现RMQ
主要思路
线段树是维护区间的一类高效数据结构,依据这个特性,我们可以用线段树实现RMQ算法,用线段树实现的RMQ算法不仅可以查询区间最小值,还可以更改某个节点的值
代码实现
#include<bits/stdc++.h>using namespace std;typedef long long int LL;const int MAXN=18;const int INF=1e9;int num[2*(1<<MAXN)];int n;void init(int base){ n=1; while(n<base){ n<<=1; } for(int i=0;i<2*n-1;i++){ num[i]=INF; }}void change_k(int k,int a){//将节点k的值赋为a k+=n-1; num[k]=a; while(k){ k=(k-1)>>1; num[k]=min(num[2*k+1],num[2*k+2]); }}int get_min(int a,int b,int k,int l,int r){ if(a<=l&&b>=r) return num[k]; else if(a>=r||b<=l) return INF; else {// cout<<l<<" "<<r<<endl; // 递归至左右子树求解 int lc=get_min(a,b,2*k+1,l,(l+r)/2); int rc=get_min(a,b,2*k+2,(l+r)/2,r); return min(lc,rc); }}int main(){ scanf("%d",&n); int cnt=n; init(n); for(int i=0;i<cnt;i++){ int tmp; scanf("%d",&tmp); change_k(i,tmp); } int a,b; scanf("%d %d",&a,&b); /* int k,num; scanf("%d %d",&k,&num); change_k(k,num); 这里还可以实现更改 */ printf("%d\n",get_min(a,b,0,0,n)==INF?-1:get_min(a,b,0,0,n));}
时间复杂度
预处理时,操作的节点个数为n+n/2+n/4+……,约为2n个,所以复杂度为O(n),每一次查询与修改区间值的复杂度是O(log n).
ST表实现RMQ
主要思路
线段树的查询复杂度为O(log n),对于有多组询问的题还是太慢,有了线段树实现的铺垫,我们思考,是否有一种方法能预先处理出区间极值呢,答案是有的,就是ST表
代码实现
#include<bits/stdc++.h>using namespace std;const int MAXN=18;int dp[(1<<MAXN)][MAXN];int a[(1<<MAXN)];int n;void st_init(){ for(int i=0;i<n;i++){ dp[i][0]=a[i]; } for(int j=1;(1<<j)<=n;j++){ for(int i=0;i+(1<<j)<=n;i++){ dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } }}int get_min(int l,int r){ int k=(int)(log((double)r-l+1)/log(2.0)); return min(dp[l][k],dp[r-(1<<k)+1][k]);}int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } st_init(); int l,r; scanf("%d %d",&l,&r); printf("%d\n",get_min(l,r));}
时间复杂度
显而易见,预处理时的复杂度是O(n log n)的,而查询的复杂度为O(1),可以高效解决多组询问的题目,但基于ST表的写法无法对区间的值进行高效更新.
阅读全文
0 0
- RMQ的两种实现方法
- RMQ的两种方法~
- RMQ的两种实现ST算法,和线段树
- 实现一个线程的两种方法
- 实现树状结构的两种方法
- 实现树状结构的两种方法
- Singleton的两种不同实现方法.
- VC++ CRC16的两种实现方法
- 实现 iSCSI Initiator 的两种方法
- javascript实现继承的两种方法
- Dorado分页的两种实现方法
- 实现 iSCSI Initiator 的两种方法
- 菜单功能的两种实现方法
- 垂直居中的两种实现方法
- android menu的两种实现方法
- 刷新UI的两种实现方法
- Android_UI_实现TabHost的两种方法
- Android 实现全屏的两种方法
- Linux Shell编程case语句-yellowcong
- CSS-position
- Servlet笔记——(2.5)Servlet方法以及Servlet域小结
- 关于系统安装的一些教程与本人的一点经验。
- 谈谈分布式事务(Distributed Transaction)[共5篇]
- RMQ的两种实现方法
- 每日新闻预测金融市场的变化_版本2
- JavaSE基础常用类
- HorizonView6.2中,错误“为设备'15'指定了不兼容的设备备用”的解决方法
- HTTP协议的8种请求类型介绍以及常见错误类型
- $ git push时候提示Everything up-to-date
- Django官方教程(十二)【编写你的第一个 Django 补丁】
- jQuery事件
- 数据库错误日志惹的祸