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

相关文章

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法

《Python错误AttributeError:NoneTypeobjecthasnoattribute问题的彻底解决方法》在Python项目开发和调试过程中,经常会碰到这样一个异常信息... 目录问题背景与概述错误解读:AttributeError: 'NoneType' object has no at