RMQ算法学习笔记

RMQ算法是什么?

以我个人的看法,与其说RMQ是算法,还不如说是一类问题,即区间(Range)最大/小值(Minimum/Maximum)查询(Query)
有三种办法可以解决这类问题
第一种是暴力查找

for(int i=n1,i<=n2;i++){
		//每次寻找是O(n)的时间复杂度
}

如果查找次数是0<n<len,那整个过程就是o(n^2)级别
预计数组规模是1e5左右就超时了
第二种
线段树o(nlogn)???这是个啥,不懂,回头再说

第三种
ST方法,可以在o(nlogn)的预处理之后做到o(1)的查询速度

原理大概是二分吧

RMQ的ST方法是怎么工作的?

分成两部分:预处理和查询

难点是循环的控制(贼难受,思考了很长时间才稍微理解)

先说预处理:
以最大值为例:
假设有数组arr,数组长度len

那么我们需要来一个二维数组dp[i][j];
i 是1<=i<=len的规模
j 是log2(len)的规模
为啥?
因为dp[i][j]的含义是从下标为i的字符开始,往后2j个字符的最大值
也就是dp[i][j] = for(arr[i]到arr[i+2j-1])的最大值
那么dp[i][0] 就是从arr[i]开始20=1个字符的最大值,这里需要说一下,我们不用0下标,也就是说dp[i][0]就是arr[i]

RMQ的时间空间复杂度?

O(nlogn)

RMQ算法的预处理是怎么处理的?

通过一个双重循环

for(int j=1;(1 << j )<=len;j++)//很奇怪是吧?为什么和以往把i放在外面的思路不一样呢?
	for(int i=1;i + (1 << j) - 1<=len;i++)
		dp[i][j] = max(dp[i][j-1],dp[i + (1 << j-1)][j-1]);

把数组原模原样的弄到dp中是这个样子的

在这里插入图片描述

之后我们把j放在外面,把i放在里面做循环,为的是让数组一列一列的dp而不是一行一行的dp,如果把i放在外面,情况就是这样的:
dp[1][1] = max(dp[1][0],dp[1+1][0]);没问题,等于1
dp[1][2] = max(dp[1][1],dp[1+2][1]);dp[1][1]是有了,但是dp[3][1]不是还没加工吗?

dp思想:也就是说,每段dp元素的值是之前已经处理过的两个元素之间的关系得出来的

然后我们先抽象的理解下这段原理
dp[i][k],也就是说把从i开始到i+2k-1个元素的最值找到并存到dp[i][k]中去,
那么我们可以吧这段分两份一起找
一份是从 i 到 i +2k-1-1

这不就是dp[i][k-1]吗

一份是从i + 2k-1到 i + 2k-1

两份长度都是2k-1

长度一样, j 值一样, i 加上 2k-1

就是dp[i+(1 << j-1)][j-1]的来历

正好凑出2k个元素

举例 dp[2][3] = max(dp[2][2] , dp[2+22][2])
在这里插入图片描述
黄色代表dp[2][2]的整体,绿色代表dp[2 + 22][2]的整体,dp[2][3]最后成绿色代表绿色找出来的值更大

RMQ的查询:

int find(int n1,int n2){//我们假设查询最大值
	int k = log2(n2-n1+1);//k是log2区间长度
	int ans = max(dp[n1][k],dp[n2-(1<<k)+1][k]);
	return ans;
}

k的作用是把区间的长度对2取对数的向下取整

找到区间n1的 j 标

这样就不把从n1开始到下标n1+2n-1的值全都检索一遍了吗

那么问题来了:

既然是向下取整,2k一定是小于等于n2-n1+1的,缺少的一部分怎么办?

我们可以直接从n2往前找

不会把,不是说 j 标是往后2j个吗?

对,所以我们直接找n2前面2k的值就可以了

也就是**dp[n2-(1<<k)+1][k]**的来历,不加+1就可能检索不到下标n2
(+1是啥我不想说了前面解释dp的 j 标的时候仔细说过了…应该能懂吧)

在这里插入图片描述
来张图片感受一下

RMQ经典题目(做到题会回来跟新的):

poj3264
uva 11235(我进不去uva网站。。。不会翻墙)

另外。。。如果对你有些帮助,可以给这个卑微大学生点一个小小的赞吗qwq

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值