RMQ问题:对于长度为N的序列,询问区间[L,R]中的最值

RMQ(Range Minimum/Maximum Query),即区间最值查询

常见解法:

1.朴素搜索

2.线段树

3.DP

4.神奇的笛卡尔树(https://www.cnblogs.com/jklongint/p/4777448.html?utm_source=tuicool

1.朴素搜索

max=a[L];
for(int i=L+1;i<=R;i++)
  if(max<a[i])
    max=a[i];
}

2.线段树https://www.cnblogs.com/jason2003/p/9676729.html

大概就是玩区间,将一个区间分为很多个小区间,分治的思想。

public class TestE {

    public static void main(String[] args) {
int[]a= {3,4,5,1,2};
SenLin sl=new SenLin(a);
sl.buildTree(0, 4, 1);
System.out.println(sl.search(0, 4, 1));
} }
class SenLin{ Tree[]N=new Tree[300];
int[] values; public SenLin(int[]values) {
this.values=values;
}
public void buildTree(int l,int r,int u) {
N[u]=new Tree();
N[u].l=l;N[u].r=r;
if(l==r) {
N[u].max=values[l];
return;
}
buildTree(l,r+l>>1,2*u);
buildTree((r+l>>1)+1,r,2*u+1);
N[u].max=Math.max(N[2*u].max, N[2*u+1].max);
}
public int search(int l,int r,int u) {
if(N[u].l==l&&N[u].r==r)
return N[u].max;
if(r<=N[2*u].r) //在左孩子的范围里
return search(l,r,2*u);
if(l>=N[2*u+1].l)//在右孩子的范围里
return search(l,r,2*u+1);
int mid=(N[u].l+N[u].r)>>1;
return Math.max(search(l,mid,2*u),search(mid+1,r,2*u+1));
}
}
class Tree{
int l;
int r;
int max;
}

3.DP

3.1预处理(时间复杂度O(nlogn))

建立dp数组,dp[i][j]表示从i开始长度为2j的区间中的最值(DP的状态)。当dp[i][0]就是从i开始长度为1的区间,就是它本身。(DP的初始值)

目的是将求从i长度为2j的大问题可以分为两个长度为2(j-1)的小问题,即[i,i+2j-1-1],[i+2j-1,i+2j-1+2j-1-1]=[i+2j-1,i+2j-1]。

因为r-l+1这个区间长度可能不是2的整数次幂,但是可以有重叠的部分,并不影响。

则可以得到:dp[i][j]=max(dp[i][j-1],dp[i+2j-1][j-1])(DP的状态转移方程)

//dp初始条件
for(int i=0;i<n;i++)
dp[i][0]=a[i];
//填表
for(int j=1;(1<<j)<=N;j++)
for(int i=0;i+(1<<j-1)<=N;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);

此处注意内外层循环,这个填表过程相当于竖着填表。

3.2查询(时间复杂度O(1))

我们回到题目:对于长度为N的序列,询问区间[L,R]中的最值,假设这里我们需要的是最大值,毋庸置疑,rmq=dp[L][m],就是从L开始,长度为2m,r-l+1=2m解得m=log2(r-l+1)问题是前文中提到得l-r+1不一定是2的整数次幂.

所以我们将其转换为求两个区间这两个区间为[l,l+2k-1][r-2k+1,r],一个确保了开头为l,另一个确保了结尾为r,得问题:rmq=max(dp[L][k],dp[r-2k+1][k]),这个2k可以是[l,r]之间重叠的部分,保证覆盖[l,r]之间所有的数。

我们要维护的两个区间是[l,l+2k-1][r-2k+1,r],为了保证覆盖[l,r]之间所有的数就要满足:l+2k-1>=r-2k+1

化简得:k>=log2(r-l+1)-1,所以k=log2(r-l+1)-1时,可以满足求得[l,r]之间得最值问题

int k=log2(r-l+1)-1
rmq=max(dp[l][k],dp[r-(1<<k)+1][k]);

static RMQ的更多相关文章

  1. 算法编程Algos Programming

    算法编程Algos Programming 不同算法的集合,用于编程比赛,如ACM ICPC. 算法按主题划分.大多数算法都可以从文件中按原样运行.每种算法都有一个参考问题,并对其时间和空间复杂度作了 ...

  2. BZOJ 3489: A simple rmq problem

    3489: A simple rmq problem Time Limit: 40 Sec  Memory Limit: 600 MBSubmit: 1594  Solved: 520[Submit] ...

  3. UVa 12299 RMQ with Shifts(移位RMQ)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: "Times New ...

  4. RMQ (Range Minimal Query) 问题 ,稀疏表 ST

    RMQ ( 范围最小值查询 ) 问题是一种动态查询问题,它不需要修改元素,但要及时回答出数组 A 在区间 [l, r] 中最小的元素值. RMQ(Range Minimum/Maximum Query ...

  5. TOJ 4325 RMQ with Shifts / 线段树单点更新

    RMQ with Shifts 时间限制(普通/Java):1000MS/3000MS     运行内存限制:65536KByte 描述 In the traditional RMQ (Range M ...

  6. UVa 12299 RMQ with Shifts(线段树)

    线段树,没了.. ----------------------------------------------------------------------------------------- # ...

  7. BZOJ 2006: [NOI2010]超级钢琴( RMQ + 堆 )

    取最大的K个, 用堆和RMQ来加速... ----------------------------------------------------------------- #include<c ...

  8. How far away ? HDU - 2586 【LCA】【RMQ】【java】

    题目大意:求树上任意两点距离. 思路: dis[i]表示i到根的距离(手动选根),则u.v的距离=dis[u]+dis[v]-2*dis[lca(u,v)]. lca:u~v的dfs序列区间里,深度最 ...

  9. 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)

    题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...

随机推荐

  1. G - Pairs Forming LCM LightOJ - 1236 (质因子分解)

    题解:这道题要从n的角度来考虑i和j. n可以表示为n=a1^p1*a2^p2*a3^p3.......n=lcm(i,j),那么质因子a1^p1,a1可以在i或者j中,并且p1=max(a1i,a1 ...

  2. 谁说 Vim 不好用?送你一个五彩斑斓的编辑器!

    相信大家在使用各种各样强大的 IDE 写代码时都会注意到,代码中各种类型的关键字会用独特的颜色标记出来,然后形成一套语法高亮规则.这样不仅美观,而且方便代码的阅读. 而在上古神器 Vim 中,我们通常 ...

  3. 爬虫实战2_有道翻译sign破解

    目标url 有道翻译 打开网站输入要翻译的内容,一一查找network发现数据返回json格式,红框就是我们的翻译结果 查看headers,发现返回结果的请求是post请求,且携带一大堆form_da ...

  4. [转载]MySQL中int(11)最大长度是多少?

    原文地址:https://blog.csdn.net/allenjay11/article/details/76549503 今天在添加数据的时候,发现当数据类型为 int(11) 时,我当时让用户添 ...

  5. mongodb权限篇

    1. 权限详解 内建角色: 数据库用户角色: read.readWrite: 数据库管理角色: dbAdmin.dbOwner.userAdmin: 集群管理角色: clusterAdmin.clus ...

  6. Python中的可视化神器!你知道是啥吗?没错就是pyecharts!

    pyecharts是一款将python与echarts结合的强大的数据可视化工具,本文将为你阐述pyecharts的使用细则 前言 我们都知道python上的一款可视化工具matplotlib,而前些 ...

  7. java集合List

    需求:List集合存储字符串并遍历.List集合的特点: 有序(存储和取出的元素一致),可重复的.package javatest; import java.util.ArrayList;import ...

  8. Docker 中如何安装配置 Nginx

    拉取 nginx 最新版镜像,然后简单启动一个 nginx 容器: docker pull nginx:latest docker run --name nginx01 -d -p 80:80 ngi ...

  9. 关于ubuntu安装vmware报错问题解决

    命令行中报错 首先报错内容为:(vmware-installer.py:3847): Gtk-WARNING **: 无法在模块路径中找到主题引擎:“murrine”, 以上的内容: sudo apt ...

  10. Linux必须会的命令---也是以前记录的,ctrl+z fg 啥的 jobs 比较实用

    fg.bg.jobs.&.ctrl + z都是跟系统任务有关的,虽然现在基本上不怎么需要用到这些命令,但学会了也是很实用的 一.& 最经常被用到 这个用在一个命令的最后,可以把这个命令 ...