RMQ问题分析

2024-05-04 06:38
文章标签 分析 问题 rmq

本文主要是介绍RMQ问题分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  RMQ问题是一类经典问题,在ACM编程竞赛中我们经常会见到它的身影。其中RMQ是Range Minimium/Maxmium Query的缩写形式,代表区间最小/最大值查询。问题描述为:对一个已知长度为n的数组a,给出多组区间[i,j],对于每个区间给出该区间的最值。该问题需要注意的地方是要处理多组数据。
  常规解法是直接遍历区间[i,j]对应的数组元素,然后找出所求的最值。该方法在只有一次查询时是最快且有效的,但是一旦有多组查询,如果每次都是孤立的进行查询,那么效率将是低下的。由此有人提出了sparse-table(st)算法,st算法维护一个稀疏矩阵st。st(i,j)表示起点为i,长度为2^j的区间的最值,这个区间为:
        [i,i+2^j-1],
显然st(i,0)=a[i]。当j!=0时,2^j为一个正偶数,我们可以将其分为两个严格相连的区间,每个区间的长度为2^(j-1)。这两个区间分别为:
        [i,i+2^(j-1)-1],[i+2^(j-1),i+2^j-1],
这里可能看得有点晕,但是慢慢推导其实很简单,都是纸老虎嘛!有了两个区间之后,原区间的最值就是这两个连续区间的最值,即动态规划的状态转移方程为(假设考虑最大值):
        st(i,j)=max{st(i,j-1),st(i+2^(j-1),j-1}。
  
对于测试用例a=[1,2,3,4,5,6],st矩阵如下所示:
  这里写图片描述
  从中我们可以看出 i[1,6] j[0,2] ,其中2由log(6-1+1)得到,即floor(log(n))。预先将st矩阵计算出来之后,接下来对于每一个查询(L,R)就可以在O(1)的时间完成,即通过floor(log(R-L+1))求出k值,利用k值得出两个区间[L,L+2^k-1],[R-2^k+1,R]。容易看出这两个区间的长度都为2^k,注意这两个区间不一定严格连续,它们可能会相交。我们在st矩阵中已经将这两个区间的最值保存起来了,因此原区间的最值也就是这两个区间的最值,即:
        max(L,R)=max{max(L,L+2^k-1),max(R-2^k+1,R)},
用st矩阵元素表示为:
        max(L,R)=max{st(L,k),st(R-2^k+1,k)},
对于上图,查询[2,6]时k=floor(log(6-2+1))=2,此时需要查找最值的两个区间为:
        [2,5],[3,6],
分别对应st矩阵中的元素:
        st[2,2],st[3,2],
因此
        max(2,6)=max{st[2,2],st[3,2]}=max{5,6}=6。
  容易看出该算法在预处理时的时间开销为O(nlogn),之后每次查询时间开销为O(1),因此总体来看该算法的时间开销是很可观的。下面给出该算法在java语言下的实现:
  

import java.util.Scanner;public class Main {private static int n;   //数组a长度private static int[] a; //待查询数组aprivate static int st[][];  //st矩阵public static int RMQ(int L,int R)  //花费O(1)时间查询最大值{if(R<L)return -1000000;int k = (int)(Math.log(R-L+1)/Math.log(2)); //分成的区间大小为2^kreturn Math.max(st[L][k], st[R-(int)Math.pow(2, k)+1][k]);}public static void ST() {   //sparse-table算法for (int i = 1; i <= n; i++) {st[i][0] = a[i];        //获取初始值}int t = (int)(Math.log(n)/Math.log(2)); //矩阵列数for (int i = 1; i <=t ; i++) {for (int j = 1; j <= n-(int)(Math.pow(2, i))+1; j++)st[j][i] = Math.max(st[j][i-1], st[j+(int)(Math.pow(2, i-1))][i-1]);}//状态转移方程}public static void main(String[] args) {n = 6;a = new int[n+1];for (int i = 1; i < a.length; i++){a[i] = i;System.out.print(a[i]+" ");}System.out.println();st = new int[n+1][(int)(Math.log(n)/Math.log(2))+1];ST();int L,R;Scanner scan = new Scanner(System.in);while(true){L = scan.nextInt();R = scan.nextInt();System.out.println(RMQ(L,R));}}
}

这篇关于RMQ问题分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/958552

相关文章

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

MySQL 设置AUTO_INCREMENT 无效的问题解决

《MySQL设置AUTO_INCREMENT无效的问题解决》本文主要介绍了MySQL设置AUTO_INCREMENT无效的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录快速设置mysql的auto_increment参数一、修改 AUTO_INCREMENT 的值。

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Java死锁问题解决方案及示例详解

《Java死锁问题解决方案及示例详解》死锁是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态,本文给大家详细介绍了Java死锁问题解决方案详解及实践样例,需要的朋友可以参考下... 目录1、简述死锁的四个必要条件:2、死锁示例代码3、如何检测死锁?3.1 使用 jstack3.2

解决JSONField、JsonProperty不生效的问题

《解决JSONField、JsonProperty不生效的问题》:本文主要介绍解决JSONField、JsonProperty不生效的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录jsONField、JsonProperty不生效javascript问题排查总结JSONField

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos