一、简介

RMQ是询问某个区间内的最大值或最小值,暴力解法对每个询问区间用循环找最值,当n、q>10000会TLE。

常用RMQ的求解方法——ST算法。

ST算法通常用在要多次询问一些区间的最值的问题中。它可以做到O(nlogn)的预处理,O(1)回答每个询问。

使用ST算法的条件是无修改,因此它适用于没有修改并且询问次数较多(10^6级别甚至更大)的情况。

优点:代码短,效率高,实现简单

缺点:适用性差

二、ST算法流程

预处理:

ST算法的原理实际上是动态规划,我们用a[1...n]表示一组数。设f[i, j]表示从a[i]到a[i + 2j - 1]这个范围内的最大值,也就是以a[i]为起点连续2j个数的最大值。由于元素个数为2j个,所以从中间平均分成两部分,每一部分的元素个数刚好为2j-1个,也就是说,把f[i,j]分为f[i, j-1]和f[i + 2j-1, j-1],如下图:

举个栗子吧——如下图所示

整个区间的最大值一定是左右两部分最大值的较大值,满足动态规划的最优化原理,分析得到状态转移方程:

f[i][j] = max(f[i][j - 1], f[i + 2j-1][j - 1]),边界条件为f[i][0] = a[i],这样就可以在O(nlogn)的时间复杂度内预处理f数组。


for(int j=;j<=LN;j++)

  for(int i=;i+(<<j)-<=n;i++)

    f[i][j]=max(f[i][j-],f[i+(<<(j-))][j-]); // <<左移运算符,优化时间常数

询问

若我们要询问区间[li, ri]的最大值,则先求出最大的x满足2x(此处为2的x次方)≤ ri - li + 1,推出x=log2(ri-li+1)

那么区间[li, ri]=[li, li+2x-1]U[ri-2x+1, ri] ,如下图所示:

ans = max(f[li][x], f[ri–2x +1][x]);

两个区间的元素个数都为2x,所以[li, ri]的最大值为max(f[li][x], f[ri - 2x + 1][x]),可以在O(1)内计算出来。虽然这两个区间有交集,但是对于求区间最值来说没有影响,这就是ST算法只适用于求区间最值的原因。

技巧:

因为cmath库中的log2函数效率不高,所以除了调用log2函数外,通常还会使用O(N)递推预处理出1~N这N种区间长度各自对应的k值。具体地,设lg[d]表示log2d下取整,log2d=log2((d/2)*2)=log2(d/2) + 1则lg[d] = lg[d/2]+1。

lg[]=-;//为了lg[1]=0;
for(int i=;i<=n;i++)
lg[i]=lg[i>>]+;// >> 右移运算符,优化时间常数

那么再来看一道例题吧——

1541:【例 1】数列区间最大值

【题目描述】

输入一串数字,给你 M 个询问,每次询问就给你两个数字 X,Y,要求你说出 X 到 Y 这段区间内的最大数。

【输入】

第一行两个整数 N,M 表示数字的个数和要询问的次数; 接下来一行为 N个数; 接下来 M行,每行都有两个整数 X,Y。

【输出】

输出共 M行,每行输出一个数。

【输入样例】

10 2

3 2 4 5 6 8 1 2 9 7

1 4

3 8

【输出样例】

5

8


RMQ问题(超详细!!!)的更多相关文章

  1. 【转】(超详细)jsp与servlet之间页面跳转及参数传递实例

    初步学习JavaEE,对其中jsp与Servlet之间的传值没弄清楚,查看网上资料,发现一篇超详细的文章,收获大大,特此记录下来.具体链接:http://blog.csdn.net/ssy_shand ...

  2. 超强、超详细Redis数据库入门教程

    这篇文章主要介绍了超强.超详细Redis入门教程,本文详细介绍了Redis数据库各个方面的知识,需要的朋友可以参考下 [本教程目录] 1.redis是什么2.redis的作者何许人也3.谁在使用red ...

  3. Github上传代码菜鸟超详细教程【转】

    最近需要将课设代码上传到Github上,之前只是用来fork别人的代码. 这篇文章写得是windows下的使用方法. 第一步:创建Github新账户 第二步:新建仓库 第三部:填写名称,简介(可选), ...

  4. WebRTC VideoEngine超详细教程(三)——集成X264编码和ffmpeg解码

    转自:http://blog.csdn.net/nonmarking/article/details/47958395 本系列目前共三篇文章,后续还会更新 WebRTC VideoEngine超详细教 ...

  5. [转]超详细图解:自己架设NuGet服务器

    本文转自:http://diaosbook.com/Post/2012/12/15/setup-private-nuget-server 超详细图解:自己架设NuGet服务器 汪宇杰          ...

  6. GitHub超详细图文攻略

    GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git 分类: 转载2014-03-25 21:10 10641人阅读 评论(2) 收藏 举报 GitHubbr ...

  7. 超详细的Xcode代码格式化教程,可自定义样式。

    超详细的Xcode代码格式化教程,可自定义样式. 为什么要格式化代码 当团队内有多人开发的时候,每个人写的代码格式都有自己的喜好,也可能会忙着写代码而忽略了格式的问题.在之前,我们可能会写完代码后,再 ...

  8. Struts2+Spring4+Hibernate4整合超详细教程

    Struts2.Spring4.Hibernate4整合 超详细教程 Struts2.Spring4.Hibernate4整合实例-下载 项目目的: 整合使用最新版本的三大框架(即Struts2.Sp ...

  9. 超全超详细的HTTP状态码大全(推荐抓包工具HTTP Analyzer V6.5.3)

    超全超详细的HTTP状态码大全 本部分余下的内容会详细地介绍 HTTP 1.1中的状态码.这些状态码被分为五大类: 100-199 用于指定客户端应相应的某些动作. 200-299 用于表示请求成功. ...

  10. 安装64位Oracle 10g超详细教程

    安装64位Oracle 10g超详细教程 1. 安装准备阶段 1.1 安装Oracle环境 经过上一篇博文的过程,已经完成了对Linux系统的安装,本例使用X-Manager来实现与Linux系统的连 ...

随机推荐

  1. .NET / C# EF中的基础操作(CRUD)

    查 public List<users> Querys() { datatestEntities db = new datatestEntities(); var a = db.users ...

  2. 一张图看懂SharpBarcode

    通过下面的图片,可以瞬间看懂整个SharpBarcode类库的脉络.

  3. HDFS文件浏览页返回上级目录功能

    1.效果预览 Hadoop自带的效果 修改后,多了一个../按钮,点击可以回到上级目录 2.查找页面和JS文件 我们在浏览器上可以看到访问了explorer.html页面,可以尝试使用find命令查找 ...

  4. 一.B/S架构和C/S架构

    1.B/S架构 Browser-Server,  浏览器和服务器架构.包含客户端浏览器.web应用服务器.数据库服务器的软件系统.用户只需要一个浏览器就可以访问服务.系统更新的时候,只需要更新服务端, ...

  5. 前端自动显示信息的小demo

    效果: //来到这个页面立即请求,展示客户公司名称 $(function () { $.ajax({ type:"GET", url:"${pageContext.req ...

  6. drf--ModelSerializers序列化

    目录 drf--ModelSerializers序列化 项目准备 配置 settings.py 路由 多表设计 表关系分析 创建models 模型序列化 自定义模型序列化 api/serializer ...

  7. 错误排查:Cloudera Manager Agent 的 Parcel 目录位于可用空间小于 10.0 吉字节 的文件系统上。 /opt/cloudera/parcels

    临时解决办法: 点击右上角的抑制,选中抑制复选框,然后重启服务即可.

  8. Flask+SQLAlchemy+graphene+docker示例

    搭建一个利用docker启动服务的Flask的小demo 定义数据库 # -*- coding: utf-8 -*- from sqlalchemy import * from sqlalchemy. ...

  9. H3C 802.11e 协议

  10. Odoo中的记录集

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826218.html 一:record set 1:获取记录集 1)在@api.multi修饰器修饰的函数 ...