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)=ai;为每个位置的元素值。

  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个询问,询问区间最大值:

  

 #include<bits/stdc++.h>
using namespace std;
int n,m,l,r,ds[],R[][];//ds即为log预处理,R表示f数组
int main()
{
scanf("%d%d",&n,&m);
ds[]=-;//方便递推
for(int i=;i<=n;i++)
{
scanf("%d",&R[i][]);
ds[i]=ds[i>>]+;
}
for(int j=;j<=;j++)
{
for(int i=;i+(j<<)-<=n;i++)
{
R[i][j]=max(R[i][j-],R[i+(<<j-)][j-]);
}
}
for(int i=;i<=m;i++)
{
scanf("%d%d",&l,&r);
int s=ds[r-l+];
printf("%d\n",max(R[l][s],R[r-(<<s)+][s]));
}
return ;
}

【学习笔记】RMQ-Range Minimum/Maximum Query (区间最小/最大值)的更多相关文章

  1. RMQ((Range Minimum/Maximum Query))ST算法

    给定一个数组,求出给定区间[l,r]中元素的最大值或最小值或者最值的索引. 一看到这个题目,简单,看我暴力出奇迹.暴力当然是可行的.但是时间复杂度很高(O(n^2)).线段树,树状数组也可以解决这个问 ...

  2. 主席树初步学习笔记(可持久化数组?静态区间第k大?)

    我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...

  3. Guava学习笔记:Range

    在Guava中新增了一个新的类型Range,从名字就可以了解到,这个是和区间有关的数据结构.从Google官方文档可以得到定义:Range定义了连续跨度的范围边界,这个连续跨度是一个可以比较的类型(C ...

  4. [一本通学习笔记] RMQ专题

    傻傻地敲了好多遍ST表. 10119. 「一本通 4.2 例 1」数列区间最大值 #include <bits/stdc++.h> using namespace std; const i ...

  5. html5学习笔记5--API Range对象(二)

    Range对象之cloneRange和cloneContents 代码效果如下 首次点击“选择内容“按钮提示如下 接着会显示 最后显示 以下为整个代码 <!DOCTYPE html> &l ...

  6. html5学习笔记4--API Range对象(一)

    Range对象基本用法 效果图如下(在谷歌浏览器下的展示)

  7. Android(java)学习笔记141:SQLiteDatabase的query方法参数分析

    public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] se ...

  8. ArcGIS API for JavaScript 4.2学习笔记[20] 使用缓冲区结合Query对象进行地震点查询【重温异步操作思想】

    这个例子相当复杂.我先简单说说这个例子是干啥的. 在UI上,提供了一个下拉框.两个滑动杆,以确定三个参数,使用这三个参数进行空间查询.这个例子就颇带空间查询的意思了. 第一个参数是油井类型,第二个参数 ...

  9. python学习笔记之——range()函数

    range函数的三种用法:>>> range(1,5) # 代表从1到5(不包含5) [1, 2, 3, 4] >>> range(1,5,2) # 代表从1到5, ...

随机推荐

  1. 简单python脚本,将jupter notebook的ipynb文件转为pdf(包含中文)

    直接执行的python代码ipynb2pdf.py 主要思路.将ipynb文件转成tex文件,然后使用latex编译成pdf.由于latex默认转换不显示中文,需要向tex文件中添加相关中文包. 依赖 ...

  2. P1197 [JSOI2008]星球大战——链式前向星+并查集

    https://www.luogu.org/problem/P1197 这道题算是关闭农场的加强版吧,数据有点大,矩阵存不下: 也是记录删点操作,从后往前加边: 先将每个点都算成一个连通块,然后每连一 ...

  3. codeforces37C

    CF37C Old Berland Language   sol:直接暴力模拟下去,长度加了就补0,凑个数就+1,凑不好就puts(“no”) #include <bits/stdc++.h&g ...

  4. SQL - where条件里的!=会过滤值为null的数据

    !=会过滤值为null的数据 在测试数据时忽然发现,使用如下的SQL是无法查询到对应column为null的数据的: select * from test where name != 'Lewis'; ...

  5. Highcharts 的使用(各种统计图)(难点:绑定数据)

    1.我们先打开 官方下载的 文件包 打开 index.htm 页面 里面有非常多的 统计图. 我是用的是3D charts 中的 3D column 也就是 3D的柱状图. 选择一个 后 会有非常棒的 ...

  6. java权限管理与用户角色权限设计

    java权限管理与用户角色权限设计 实现业务系统中的用户权限管理 B/S系统中的权限比C/S中的更显的重要,C/S系统因为具有特殊的客户端,所以访问用户的权限检测可以通过客户端实现或通过客户端+服务器 ...

  7. Flask上下文源码分析(二)

    前面第一篇主要记录了Flask框架,从http请求发起,到返回响应,发生在server和app直接的过程. 里面有说到,Flask框架有设计了两种上下文,即应用上下文和请求上下文 官方文档里是说先理解 ...

  8. boost 线程库

    http://www.boost.org/ Boost的安装 step1.从www.boost.org下载boost库 step2 在 tools\build\jam_src目录下 运行build.b ...

  9. 分享一款颜色神器ColorSchemer Studio

    ColorSchemer Studio是一款专业配色软件,网页设计或平面设计师必备工具,和ColorPix V1.2 屏幕取色同属一个公司佳作,使用ColorSchemer Studio吸取屏幕任一色 ...

  10. export命令import命令

    export命令import命令 export { name1, name2, …, nameN }; export { variable1 as name1, variable2 as name2, ...