浅谈RMQ问题
RMQ:question
有一个长度为
N
N
N的数组,数组中的数是无序的(
1
<
=
n
<
=
5
∗
1
0
5
1<=n<=5*10^5
1<=n<=5∗105)。
给定
Q
Q
Q次查询,每次给出一个区间
[
L
,
R
]
[L,R]
[L,R],问区间最值是多少。
Q
Q
Q为
3
×
1
0
6
3×10^6
3×106
浅浅地分析下?
我们拿到题的第一感觉?
- 肯定是暴力枚举
- 不做任何处理,直接查询(这谁都会吧)
- O
(
Q
∗
n
2
)
O(Q*n^2)
O(Q∗n2),时间难以承受
思考下,暴力储存?
- 因为这是区间问题,考虑区间dp?
- F
[
i
]
[
j
]
表示区间
[
i
,
j
]
内的最值
F[i][j]表示区间[i,j]内的最值
F[i][j]表示区间[i,j]内的最值
- 处理:
O
(
n
3
)
O(n^3)
O(n3),查询:
O
(
1
)
O(1)
O(1),比上个好了点,但是还是无法承受。
进一步思考?
- 我们上一个方案的状态转移方程是什么?
- F
[
i
]
[
j
]
=
m
a
x
(
f
[
i
]
[
k
]
,
f
[
k
+
1
]
[
j
]
)
(
i
<
=
k
<
=
j
)
不需要循环枚举
F[i][j]=max(f[i][k],f[k+1][j])(i<=k<=j)不需要循环枚举
F[i][j]=max(f[i][k],f[k+1][j])(i<=k<=j)不需要循环枚举
- 所以,我们真的需要那么多空间吗?
- 于是,我们可以将
F
F
F数组的含义变为
- F
[
i
]
[
k
]
表示区间
[
i
,
i
+
k
−
1
]
的最值
F[i][k]表示区间[i,i+k-1]的最值
F[i][k]表示区间[i,i+k−1]的最值
- 这样依旧会爆,但是这是我们迈出成功地一大步
最终?
- 这个时候,就有一个很厉害的东西: ST表
- 这个是什么呢?请看
- F
[
i
]
[
j
]
表示区间
[
i
,
i
+
2
j
−
1
]
内的最值
F[i][j]表示区间[i,i+2^j-1]内的最值
F[i][j]表示区间[i,i+2j−1]内的最值
- 这时候,空间就不会爆!
- 转移方程::
F
[
i
]
[
j
]
=
m
a
x
(
F
[
i
]
[
j
−
1
]
,
F
[
i
]
[
i
+
(
1
<
<
(
j
−
1
)
)
]
F[i][j]=max(F[i][j-1],F[i][i+(1<<(j-1))]
F[i][j]=max(F[i][j−1],F[i][i+(1<<(j−1))]
- <
<
是左移,
1
<
<
j
=
2
j
<<是左移,1<<j=2^j
<<是左移,1<<j=2j,其实
<
<
<<
<<的优先级比
−
-
−低,所以最里面的括号可以删掉
- 最后是:
F
[
i
]
[
i
]
=
m
a
x
(
F
[
i
]
[
j
−
1
]
,
F
[
i
]
[
i
+
(
1
<
<
j
−
1
)
]
F[i][i]=max(F[i][j-1],F[i][i+(1<<j-1)]
F[i][i]=max(F[i][j−1],F[i][i+(1<<j−1)]
- 为什么?
- 我举个例子:
F
[
1
]
[
3
]
F[1][3]
F[1][3]表示的是
区间
[
1
,
1
+
2
3
]
=
[
1
,
8
]
,
区间[1,1+2^3]=[1,8],
区间[1,1+23]=[1,8],他就可以从
区间
F
[
1
,
4
]
和
F
[
5
,
8
]
区间F[1,4]和F[5,8]
区间F[1,4]和F[5,8]表示
- 怎么查询?
- 我们可以考虑快速幂,比如
10
10
10二进制表示
1010
1010
1010,所以比较大小
2
,
8
2,8
2,8的区间即可
终极优化
- 如果区间大小是31
- 那么我们得连续比较
16
,
8
,
4
,
2
,
1
16,8,4,2,1
16,8,4,2,1的区间
- 复杂度可以接受,但是我们可以继续优化时间复杂度

- 这张图片告诉我们什么道理?
- 比较区间是可以重叠的!!
- 那么我们这需要求出
l
o
g
2
n
{log_{2}}^{n}
log2n即可
- 比如
31
31
31,我们可以把它拆成
[
1
,
16
]
[
15
,
31
]
[1,16][15,31]
[1,16][15,31]来比较,如果预先处理好
l
o
g
2
n
{log_{2}}^{n}
log2n我们就可以以
O
(
1
)
O(1)
O(1)的复杂度查询!
怎么预先处理
l
o
g
2
n
{log_{2}}^{n}
log2n
- 有个代码可以比
c
m
a
t
h
cmath
cmath的函数快很多
C
o
d
e
:
Code:
Code:
for(int i=1;i<=n;++i)
lg[i]=lg[i-1]+((1<<lg[i-1])==i);
- 但是这里有个
B
U
G
BUG
BUG!如果你要求
l
o
g
2
n
{log_{2}}^{n}
log2n,你需要减一
C
o
d
e
Code
Code(我自己写的模板)
#include<bits/stdc++.h>
using namespace std;
int n,m,dp[2][2000005],lo[2000005],a[2000005];
void log_2(){//求log2 n
for(int i=1;i<=n;i++)
lo[i]+=lo[i-1]+((1<<lo[i-1])==i);
}
int main()
{
cin>>n>>m;
log_2();
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
dp[i][j]=1e9;
for(int i=1;i<=n;i++) dp[0][i]=a[i];
//初始化rmq,区间dp
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
dp[i][j]=min(dp[i-1][j],dp[i-1][j+(1<<i-1)]);
//查询
cout<<0<<endl;//题目所需QWQ
for(int w=2;w<=n;w++){
int j=w-m,i=w-1;
if(j<=0) j=1;
int k=lo[i-j+1]-1;//注意减一
cout<<min(dp[k][j],dp[k][i-(1<<k)+1])<<endl;
}
return 0;
}
注明
我这个代码是基于P1440 求m区间内的最小值的80分代码,因为本蒟蒻太蒟了,不会滚动数组,大家可以拿这道题练练手
关于这道题:
(老师提醒)
因为这题的区间长度只有m,所以可以用滚动数组,减小空间复杂度,不MLE
(自己提醒)
不要用memset!不要用memset!用了直接全部MLE,因为

浅谈RMQ问题的更多相关文章
- 浅谈-RMQ
浅谈RMQ Today,我get到了一个新算法,开心....RMQ. 今天主要说一下RMQ里的ST算法(Sparse Table). RMQ(Range Minimum/Maximum Query), ...
- 浅谈RMQ
RMQ是一类求区间极值的问题 有一种 \(O\left(nlogn\right)\) 的解法,用倍增实现 倍增算法 变量的定义 \(A_i\) : 原数组 \(f_{i,j}\) : 以 \(i\) ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
随机推荐
- 一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 41.spring的事务传播机制 42 .spring事务什么时候会失效 43 .什么的是bean的自动装配.有哪些方式? ...
- centos 7.6镜像_Centos7 配置本地yum源为iso镜像
创建挂载路径 sudo mkdir /media/iso 挂载ISO镜像到目录 sudo mount -o loop CentOS-7-x86_64-Minimal-1810.iso /media/i ...
- Codeforces Round #820 (Div. 3) A-G
比赛链接 A 题解 知识点:模拟 时间复杂度 \(O(1)\) 空间复杂度 \(O(1)\) 代码 #include <bits/stdc++.h> #define ll long lon ...
- 开源项目在线化 中文繁简体转换/敏感词/拼音/分词/汉字相似度/markdown 目录
前言 以前在 github 上自己开源了一些项目.碍于技术与精力,大部分项目都是 java 实现的. 这对于非 java 开发者而言很不友好,对于不会编程的用户更加不友好. 为了让更多的人可以使用到这 ...
- linux系统移植
1 linux环境搭建 1.1 添加交叉开发工具链 新建如下工程目录: gcc-4.6.4.tar.xz #拷贝 tar -Jxvf gcc-4.6.4.tar.xz #解压 cd ./gcc-4.6 ...
- adb版本不同导致一个服务杀死另一个服务
前言 由于我用安装模拟器进行调试app,需要连接到固定端口, 而开发测试的时候用到eclipse中调用sdk中包含一个版本的adb, 另外Android killer中也包含一个版本的adb, 另外我 ...
- ArcObjects SDK开发 001 ArcObjects SDK 简介
1.什么是ArcObjects SDK 在网上搜索什么是ArcObjects,会搜到如下的定义. 这个定义比较准确,也比较容易理解. 2.什么是ArcEngine 在网上搜索ArcEngine,一般会 ...
- MySQL锁,锁的到底是什么?
MySQL锁系列文章已经鸽了挺久了,最近赶紧挤了挤时间,和大家聊一聊MySQL的锁. 只要学计算机,「锁」永远是一个绕不过的话题.MySQL锁也是一样. 一句话解释MySQL锁: MySQL锁是解决资 ...
- 【kafka】connect的timestamp模式无法同一秒插入多条记录问题解决
一.现在问题 同时插入多条时间戳相同的记录 INSERT INTO "ABANK" VALUES ('1', 'CH', '00211', 'UBS Switzerland AG' ...
- JavaEE Day05 JDBC(用Java语言操作数据库)
今日内容 基本概念 快速入门 对JDBC中各个接口和类的详解 一.基本概念 1.概念:Java Database Connectivity:Java数据库连接,Java语言操作数据库 2.本质:官方( ...