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

相关文章

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基