RMQ区间最值查询

概述

RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,

回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。这两个问题是在实际应用中经

常遇到的问题,下面介绍一下解决这两种问题的比较高效的算法。

分析:

对于该问题,最容易想到的解决方案是遍历,复杂度是O(n)。但当数据量非常大且查询很频繁时,该算法无法

在有效的时间内查询出正解。

这里介绍Tarjan的Sparse-Table算法,预处理时间为O(nlogn),但查询只需要O(1),并且常数很小,算法也很容易写出。

预处理

设A[i]是要求区间最值的数列,F[i, j]  表示从第  i 个数起连续  2  个数中的最大值。(DP的状态)

例如 A 数列为:3 2 4 5 6 8 1 2 9 7

F[1,0]表示第1个数起,长度为20=1的最大值,其实就是3这个数。

同理 F[1,1] = max(3,2) = 3, F[1,2]=max(3,2,4,5) = 5,F[1,3] = max(3,2,4,5,6,8,1,2) = 8;

首先:F[i,0]就等于A[i]。(DP的初始值)

其次:我们把F[i,j]平均分成两段(因为f[i,j]一定是偶数个数字),从 i 到i + 2 (j - 1) - 1为一段,i + 2  (j - 1)  到 i + 2 j - 1为一段

于是我们得到了

状态转移方程             F[i, j]=max(F[i,j-1], F[i + 2(j-1),j-1])

void RMQ_init(const vector<int> &A) {
int n = A.size();
for(int i = 0; i < n; ++i) d[i][0] = A[i];
for(int j = 1; (1 << j) <= n; ++j)
for(int i = 0; i + (1 << j) - 1 < n; ++i)
d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
}

查询:

假如我们需要查询的区间为(i,j),那么我们需要找到覆盖这个闭区间(左边界取i,右边界取j)的最小幂

因为这个区间的长度为  j - i + 1,所以我们可以取   k=log2( j - i + 1) ,则有:RMQ(A, i, j)=max{   F[i , k] ,   F[ j - 2 k + 1, k]   }
举例说明,要求区间[2,8]的最大值,k = log2(8 - 2 + 1)= 2,即求max(F[2, 2],F[8 - 2 2 + 1, 2]) = max(F[2, 2],F[5, 2]);

 int RMQ(int L, int R) {
int k = 0;
while((1 << (k + 1)) <= R - L + 1) ++k;
return max(d[L][k], d[R - (1 << k) + 1][k]);
}

例题:

题目描述

老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记k次账,
由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。
于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3…编号,然后不定时的问管家问题,
问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。

输入格式:

输入中第一行有两个数m,n表示有m(m<=100000)笔账,n表示有n个问题,n<=100000。
第二行为m个数,分别是账目的钱数
后面n行分别是n个问题,每行有2个数字说明开始结束的账目编号。

输出格式:

输出文件中为每个问题的答案。具体查看样例。

输入输出样例

输入样例#1:
10 3
1 2 3 4 5 6 7 8 9 10
2 7
3 9
1 10
输出样例#1:

2 3 1

代码:

#include<iostream>
#include<bits/stdc++.h>
using namespace std; int dp[500100][20];//dp[i][j]是从第i个数起,到第2^j个数止的,最小值
int main(){
int n,q;
cin>>n>>q;
int *arr = new int[n+1];
for (int i = 1; i <= n; i++){
cin>>arr[i];
} for (int i = 1; i <= n; i++) dp[i][0]=arr[i];
int count=0;
while((1<<count)<=n)count++;
// cout<<"count="<<count<<" "<<endl;
for(int j=1;j<=count;j++)
for(int i=1;i<=n;i++)
dp[i][j]=min(dp[i][j-1],dp[i+ (1<< (j-1) ) ][j-1]);
int L,R,k;
while (q--){
cin>>L>>R;
k=0;
while (1<<(k+1)<=R-L+1)k++;
cout<<min(dp[L][k],dp[R-(1<<k)+1][k])<<" ";
}
}

RMQ区间最值查询的更多相关文章

  1. 【RMQ】 区间最值查询详解

    1. 概述 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A ...

  2. HDU 1754 I Hate It(线段树之单点更新 区间最值查询)

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  3. POJ 3264:Balanced Lineup(区间最值查询ST表&线段树)

      Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 75294   Accepted: 344 ...

  4. hdu1754 I hate it线段树模板 区间最值查询

    题目链接:这道题是线段树,树状数组最基础的问题 两种分类方式:按照更新对象和查询对象 单点更新,区间查询; 区间更新,单点查询; 按照整体维护的对象: 维护前缀和; 维护区间最值. 线段树模板代码 # ...

  5. NBOJv2 1004 蛤玮打扫教室(线段树区间更新区间最值查询)

    Problem 1004: 蛤玮打扫教室 Time Limits:  1000 MS   Memory Limits:  65536 KB 64-bit interger IO format:  %l ...

  6. HDU 1754 I Hate It(线段树单点更新区间最值查询)

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  7. RMQ(区间最值问题)

    问题: RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大) ...

  8. nyoj 119士兵杀敌(三)(线段树区间最值查询,RMQ算法)

    题目119 题目信息 执行结果 本题排行 讨论区 士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描写叙述 南将军统率着N个士兵,士兵分别编号为1~N,南将军常 ...

  9. RMQ 区间最大值 最小值查询

    /*RMQ 更新最小值操作 By:draymonder*/ #include <iostream> #include <cstdio> using namespace std; ...

随机推荐

  1. Logback 快速入门 / 使用详解

    官方文档: http://logback.qos.ch/manual/index.html 一.简介 Java 开源日志框架,以继承改善 log4j 为目的而生,是 log4j 创始人 Ceki Gü ...

  2. 如何远程调试自定义开发的Flume应用

    一.前言 Flume作为当下最流行的大数据采集组件之一.其本身拥有分布式/高可靠/高可用等优点,但相比较于Flink/Spark/Kafka等大数据组件,其对于本地调试的功能支持度并不高,如果我们没有 ...

  3. SQL 练习8

    查询「李」姓老师的数量 SELECT Tname,COUNT(Tname)数量 from Teacher GROUP BY tname HAVING Tname LIKE '李%'

  4. MySQL主从复制与Atlas读写分离

    配置主从复制 1. 增加主从配置 # 主库配置文件 server-id = 1 log-bin = /var/lib/mysql/mysql-bin expire_logs_days = 10 ski ...

  5. vue引入zTree入门

    参考1:https://blog.csdn.net/tg928600774/article/details/80911589 参考2:https://blog.csdn.net/ylhsuper/ar ...

  6. MVVMLight学习笔记(四)---RelayCommand初探

    一.概述 在MVVM Light框架中,主要通过命令绑定来进行事件的处理. WPF中,命令是通过实现 ICommand 接口创建的. ICommand 公开了两个方法(Execute 及 CanExe ...

  7. Spring第一课:核心API(三)

    以上是Spring的核心部分,其中需要了解的是:BeanFactory.ApplicationContext[FileSystemXmlApplicationContext.ClassPathXmlA ...

  8. JAVA 各种时间类型转换

    final Date date = new Date(); final Timestamp timestamp = new Timestamp(date.getTime()); final Calen ...

  9. UVA1620 Lazy Susan(结论证明)

    结论: 当 \(n\geq 6\) 时,若 \(n\) 是奇数且输入序列的逆序对数是奇数,则无解,否则有解. 当 \(n=4\) 或 \(n=5\) 时,答案个数及其有限,只有这个环是 \(1\) 到 ...

  10. ES6扩展——对象的扩展(简洁表示法与属性名表达式)

    1.简洁表达法. 当属性名与属性值相同时,可省略属性值:例如:{name : name}可以写成 {name} 属性方法中,可省略冒号与function,直接 属性名(){}即可.例如{say : f ...