『数据结构』RMQ问题
RMQ(Range Minimum/Maximum Query),即区间最值问题。
对于长度为 n 的数列 A ,回答若干查询 RMQ(A,i,j)(i,j<=n) ,返回数列 A 中下标在 i,j 里的最大(小)值。
相关算法
- 朴素(搜索),时间复杂度:\(O(n)-O(q \times n)\) ,在线;
- 线段树,时间复杂度:$O(n)-O(q\times logn) $,在线;
ST(动态规划),时间复杂度:\(O(n\times logn)-O(q)\),在线;RMQ标准算法,先规约为LCA,再规约成约束RMQ,时间复杂度:\(O(n)-O(q)\),在线。
ST 算法
假设当前题目要求区间最小值,我们令 dp[i][j] 代表从 i 开始,长度为\(2^{j}\)这段区间的最小值。
于是便有:\(dp[i][j]=min(dp[i][j-1],dp[i+^{j-1}][j-1])\)
分析可知,\(dp[i][j-1]\)代表从 i 开始,长度为\(2^{j}\)区间一半中的最小值,而 \(dp[i+2^{j-1}][j-1]\)即为区间的另一半。
即为区间的另一半。
最终(从下往上看):
| \(dp[0][*]\) | \(dp[1][*]\) | \(dp[2][*]\) | \(dp[3][*]\) | \(dp[4][*]\) | \(dp[5][*]\) | \(dp[6][*]\) | \(dp[7][*]\) | |
|---|---|---|---|---|---|---|---|---|
| \(dp[*\)][3] | \(1\) | |||||||
| \(dp[*\)][2] | \(1\) | \(1\) | \(1\) | \(5\) | \(2\) | |||
| \(dp[*][1]\) | \(3\) | \(1\) | \(1\) | \(5\) | \(7\) | \(6\) | \(2\) | |
| \(dp[*][0]\) | \(4\) | \(3\) | \(1\) | \(5\) | \(7\) | \(8\) | \(6\) | \(2\) |
预处理
根据状态转移方程,首先指定当区间长度为\(2^{0}\)时的各初始值,随后推出后面的结果。
void ST_Init(const vector<int> &A) {
int n=A.size();
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]);
}
查询
预处理出整个 dp 数组以后,查询操作很简单,令 k 为满足\(2^{k} \leq R-L+1\)的最大整数,则以 L 开头、以 R 结尾的两个长度为\(2^{k}\)的区间合起来即覆盖了查询区间 [L,R] 。
int RMQ(int L, int R) {
int k=0;
while ((1<<(k+1))<=R-L+1) k++;
return min(dp[L][k], dp[R-(1<<k)+1][k]);
}
嗯!怎么说呢?感觉线段树在这种类型的题目中好像是最万能的方法了。
无论是 [点修改+查询] 还是 [区间修改+查询] ,它都可以做到 \(O(logn)\)的复杂度,而且在线段树中我们也可以维护好多东西(区间和、最值等等)。
对于一维中的线段树,我们想要查询某个区间的最值,首先就应该建树咯~(具体方法省略)
而在查询时,我们可以从根节点向下递归搜索,如下图,假设查询区间为 [2,6] 。
将 [2,6] 这一个大区间分解为不相交的三个小区间 [2,3]、[4,5]、[6] ,而最终的结果便由这三个节点中所维护的信息决定的!

我们假设查询还是区间最小值,于是最终的结果为\(\min(1,7,6)=1\)
线段树可以解决普通的 [点/区间] 修改+查询 ,当然它也可以解决 树中的路径权值 修改+查询(树链剖分)。
『数据结构』RMQ问题的更多相关文章
- 『图论』LCA 最近公共祖先
概述篇 LCA (Least Common Ancestors) ,即最近公共祖先,是指这样的一个问题:在一棵有根树中,找出某两个节点 u 和 v 最近的公共祖先. LCA 可分为在线算法与离线算法 ...
- 『TensotFlow』RNN中文文本_下_暨研究生开学感想
承前 接上节代码『TensotFlow』RNN中文文本_上, import numpy as np import tensorflow as tf from collections import Co ...
- 『TensotFlow』RNN中文文本_上
中文文字预处理流程 文本处理 读取+去除特殊符号 按照字段长度排序 辅助数据结构生成 生成 {字符:出现次数} 字典 生成按出现次数排序好的字符list 生成 {字符:序号} 字典 生成序号list ...
- 『PyTorch』第三弹重置_Variable对象
『PyTorch』第三弹_自动求导 torch.autograd.Variable是Autograd的核心类,它封装了Tensor,并整合了反向传播的相关实现 Varibale包含三个属性: data ...
- 『Json』常用方法记录
json模块可以把字典结构改写为string然后保存,并可以反向读取字典 pickle模块则可以持久化任意数据结构 但是即使同样是字典数据结构,两个包也是有差别的, json字典value不支持其他对 ...
- 『StabilityGuide』| 10+位阿里技术专家共同发起稳定性知识库开源项目
我们穿过山和大海,也见过人山人海.我们见过各类故障,也排过千雷万险.这一次,不如我们一起,开启稳定性的探索之旅.让无法解决的问题少一点点,让世界的确定性多一点点. 无论是前端业务的开发者,还是后端架构 ...
- 『AngularJS』$location 服务
项目中关于 $location的用法 简介 $location服务解析在浏览器地址栏中的URL(基于window.location)并且让URL在你的应用中可用.改变在地址栏中的URL会作用到$loc ...
- [原创] 【2014.12.02更新网盘链接】基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装
[原创] [2014.12.02更新网盘链接]基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装 joinlidong 发表于 2014-11-29 14:25:50 ...
- JS 中通过对象关联实现『继承』
JS 中继承其实是种委托,而不是传统面向对象中的复制父类到子类,只是通过原型链将要做的事委托给父类. 下面介绍通过对象关联来实现『继承』的方法: Foo = { // 需要提供一个 init 方法来初 ...
随机推荐
- springboot+thymeleaf国际化方法一:LocaleResolver
springboot中大部分有默认配置所以开发起项目来非常迅速,仅对需求项做单独配置覆盖即可 spring采用的默认区域解析器是AcceptHeaderLocaleResolver,根据request ...
- JAVA之类的动手动脑
1.默认构造方法与自定义的构造方法的冲突 package com.xu; class fool { int value; fool(int nowvalue) { value=nowvalue; } ...
- Web安全之url跳转漏洞及bypass总结
0x01 成因 对于URL跳转的实现一般会有几种实现方式: META标签内跳转 javascript跳转 header头跳转 通过以GET或者POST的方式接收将要跳转的URL,然后通过上面的几种方式 ...
- Msfvenom命令总结大全
1. –p (- -payload-options) 添加载荷payload. 载荷这个东西比较多,这个软件就是根据对应的载荷payload生成对应平台下的后门,所以只有选对payload,再填 ...
- webapck 按需加载及版本控制问题
在启用webpack的懒加载(按需加载)后,我们会遇到要解决缓存的问题. 解决缓存问题有几种方法: 第一种就是加个hash值.便每次修改后所编译后的文件名都不一样.这样能达到预期解决缓存的效果.具体设 ...
- HDU 6045 Is Derek lying?
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6045 题目: Is Derek lying? Time Limit: 3000/1000 MS (Ja ...
- Swoole 的微信扫码登录
微信应用的便捷,扫码登录方式越来越被现在的应用所使用.它因为不用去记住密码,只要有微信号即可方便快捷登录.微信的开放平台原生就有支持扫码登录的功能,不过大部分人还是在用公众平台,所以扫码登录只能自行实 ...
- Java中常用的四种线程池
在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解.不过,在Executors类中,为我们提供了常用线程 ...
- .NET Core 3.0 本地工具
.NET Core从最早期的版本就开始支持全局工具了.如果仅仅需要在某个项目中或某个文件夹中使用特定的工具,那么.NET Core 3.0就允许您这样做. 使用.NET Core 3.0,您可以在特定 ...
- (day31) Event+协程+进程/线程池
目录 昨日回顾 GIL全局解释器锁 计算密集型和IO密集型 死锁现象 递归锁 信号量 线程队列 FOFI队列 LIFO队列 优先级队列 今日内容 Event事件 线程池与进程池 异步提交和回调函数 协 ...