【学习笔记】RMQ-RangeMinimumMaximumQuery(区间最小最大值)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【学习笔记】RMQ-RangeMinimumMaximumQuery(区间最⼩
最⼤值)
RMQ是⼀类询问区间最⼩/最⼤值的问题。

这类问题⼀般分成两类:静态区间(⽆修改),动态区间(带修改)。

对于动态区间查询最⼤/最⼩,我们显然可以⽤线段树来解决……
那么对于静态区间查询最⼤/最⼩的问题,我们⼀般⽤ST算法解决。

(显然这个我们也可以⽤线段树)
这个算法相⽐于线段树来说有以下优点:
·程序实现⽐较简单。

·运⾏速度快,常数⼩。

接下来为了解释⽅便,我们假设我们要查询区间的最⼤值。

⼀.ST算法的实质
ST算法的实质是动态规划。

现在我们有⼀组数a[1…n];
我们定义f(i,j)表⽰从a[i]开始,向后长度为2j的区间中最⼤值。

基于分治思想,我们可以把这段区间分为两部分,每⼀部分的长度恰好是2j-1。

那么显然有以下转移⽅程:
f(i,j)=max(f(i,j-1),f(i+2j-1,j-1);
这就是ST算法的实质,下⾯介绍ST算法的流程。

⼆.ST算法的流程
1.预处理
上⾯我们提到过,ST算法的实质就是动态规划。

那么我们通过枚举i和j来预处理f数组,复杂度为O(nlogn)。

状态转移⽅程:f(i,j)=max(f(i,j-1),f(i+2j-1,j-1);
边界条件:f(i,0)=a i;为每个位置的元素值。

2.询问
如果我们要询问区间[l,r]的最⼤值,我们同样把这个区间分为两个部分,但这次我们将这个区间分为两个有交集区间。

根据f数组的第⼆维,我们找到⼀个数x满⾜2x≤r-l+1,然后把区间分为[l,l+2x-1]和[r-2x+1,r],显然这两个区间的并集就是我们要查找的区间[l,r]。

通过这样的处理,这两个区间的元素正好是2的正次幂,所以[l,r]区间的最⼤值为max(f(l,x),f(r-2x+1,x)),查询操作的复杂度是O(1)。

那么我们要求区间[l,r]的最⼤值,有以下表达式:
k=log2(r-l+1);
ans=max(f[l][k],f[r-2k+1][k]);
通过这些我们可以发现,ST算法适⽤于没有修改操作并且询问次数较多的RMQ问题。

三.⼀些技巧
我们可以⽤O(n)的额外时间预处理出log数组,这个过程是递推的,根据函数本⾝定义我们可以得到以下式⼦: log(x)=log(x/2)+1;
四.代码
有N个数,M个询问,询问区间最⼤值:
1 #include<bits/stdc++.h>
2using namespace std;
3int n,m,l,r,ds[1000010],R[1000010][21];//ds即为log预处理,R表⽰f数组
4int main()
5 {
6 scanf("%d%d",&n,&m);
7 ds[0]=-1;//⽅便递推
8for(int i=1;i<=n;i++)
9 {
10 scanf("%d",&R[i][0]);
11 ds[i]=ds[i>>1]+1;
12 }
13for(int j=1;j<=20;j++)
14 {
15for(int i=1;i+(j<<1)-1<=n;i++)
16 {
17 R[i][j]=max(R[i][j-1],R[i+(1<<j-1)][j-1]);
18 }
19 }
20for(int i=1;i<=m;i++)
21 {
22 scanf("%d%d",&l,&r);
23int s=ds[r-l+1];
24 printf("%d\n",max(R[l][s],R[r-(1<<s)+1][s]));
25 }
26return0;
27 }
View Code。

相关文档
最新文档