简介

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

RMQ(Range Minimum/Maximum Query),即区间最值查询,这是一种在线算法,所谓在线算法,是指用户每次输入一个查询,便马上处理一个查询。RMQ算法一般用较长时间做预处理,时间复杂度为O(nlogn),然后可以在O(1)的时间内处理每次查询。

示例:

问题:给出n个数ai,让你快速查询某个区间的的最值。

算法分类:DP+位运算

算法分析:这个算法就是基于DP和位运算符,我们用dp【i】【j】表示从第 i 位开始,到第 i + 2^j -1 位的最大值或者最小值。

那么我求dp【i】【j】的时候可以把它分成两部分,第一部分从 i 到 i + 2 ^( j-1 ) - 1 ,第二部分从 i + 2 ^( j-1 )  到 i + 2^j - 1 次方,其实我们知道二进制数后一个是前一个的二倍,那么可以把 i ---  i + 2^j  这个区间 通过2^(j-1) 分成相等的两部分, 那么转移方程很容易就写出来了。

转移方程: mm [ i ] [ j ] = max ( mm [ i ] [ j - 1 ] , mm [ i + ( 1 << ( j - 1 ) ) ] [ j - 1 ] );

代码:

void rmq_isit(boolok)

{for(int i=1;i<=n;i++)

mm[i][0]=mi[i][0]=a[i];for(int j=1;(1<

{for(int i=1;i+(1<

{if(ok)

mm[i][j]=max(mm[i][j-1],mm[i+(1<

}

}

}

那么查询的时候对于任意一个区间 l -- r ,我们同样可以得到区间差值 len = (r - l + 1)。

那么我们这一用小于2^k<=len,的 k 把区间分成可以交叉的两部分l 到 l+2^(k)- 1, 到 r -(1<

查询代码:

int rmq(int l,intr)

{int k=0;while((1<

k++;//printf("%d %d %d %d\n",l,l+(1<

int ans1=max(mm[l][k],mm[r-(1<

}

主要方法及复杂度如下:

1、朴素(即搜索),O(n)-O(qn) online。

2、线段树,O(n)-O(qlogn) online。

3、ST(实质是动态规划),O(nlogn)-O(q) online。

ST算法(Sparse Table),以求最大值为例,设d[i,j]表示[i,i+2^j-1]这个区间内的最大值,那么在询问到[a,b]区间的最大值时答案就是max(d[a,k], d[b-2^k+1,k]),其中k是满足2^k<=b-a+1(即长度)的最大的k,即k=[ln(b-a+1)/ln(2)]。

d的求法可以用动态规划,d[i, j]=max(d[i, j-1],d[i+2^(j-1), j-1])。

4、RMQ标准算法:先规约成LCA(Lowest Common Ancestor),再规约成约束RMQ,O(n)-O(q) online。

首先根据原数列,建立笛卡尔树,从而将问题在线性时间内规约为LCA问题。LCA问题可以在线性时间内规约为约束RMQ,也就是数列中任意两个相邻的数的差都是+1或-1的RMQ问题。约束RMQ有O(n)-O(1)的在线解法,故整个算法的时间复杂度为O(n)-O(1)。

ST算法

来看一下ST算法是怎么实现的(以最大值为例):

首先是预处理,用一个DP解决。设a是要求区间最值的数列,f[i,j]表示从第i个数起连续2^j个数中的最大值。例如数列3 2 4 5 6 8 1 2 9 7 ,f[1,0]表示第1个数起,长度为2^0=1的最大值,其实就是3这个数。f[1,2]=5,f[1,3]=8,f[2,0]=2,f[2,1]=4……从这里可以看出f[i,0]其实就等于a[i]。这样,DP的状态、初值都已经有了,剩下的就是状态转移方程。我们把f[i,j](j≥1)平均分成两段(因为j≥1时,f[i,j]一定是偶数个数字),从i到i+2^(j-1)-1为一段,i+2^(j-1)到i+2^j-1为一段(长度都为2^(j-1))。用上例说明,当i=1,j=3时就是3,2,4,5 和6,8,1,2这两段。f就是这两段的最大值中的最大值。于是我们得到了动规方程F[i,j]=max(F[i,j-1],F[i+2^(j-1),j-1])。

接下来是得出最值,也许你想不到计算出f有什么用处,一般要想计算max还是要O(logn),甚至O(n)。但有一个很好的办法,做到了O(1)。还是分开来。如在上例中我们要求区间[2,8]的最大值,就要把它分成[2,5]和[5,8]两个区间,因为这两个区间的最大值我们可以直接由f[2,2]和f[5,2]得到。扩展到一般情况,就是把区间[l,r]分成两个长度为2^n的区间(保证有f对应)。直接给出表达式:

k:=trunc(ln(r-l+1)/ln(2));

ans:=max(F[l,k],F[r-2^k+1,k]);

这样就计算了从l开始,长度为2^k的区间和从r-2^k+1开始长度为2^k的区间的最大值(表达式比较繁琐,细节问题如加1减1需要仔细考虑),二者中的较大者就是整个区间[l,r]上的最大值。

标准算法

建立笛卡尔树

数组A[0,N-1]的笛卡尔树C是这样一棵二叉树:当N=0,它是一棵空树,否则它的根节点是A中的一个最小元素A[i](并以这个最小元素的下标i标记),而左右子树分别是A[0,i-1]和A[i+1,N-1]的一棵笛卡尔树。注意如果A中有相等的元素,则A的笛卡尔树不一定唯一,但在这里我们限定所用的最小元素为在数组中最先出现者,在此限制下笛卡尔树是唯一的。

容易看出,数组A在闭区间[l,r]上的最小值等同于笛卡尔树C中下标为l和r的两个顶点的最近公共祖先(LCA)的值。由此,RMQ问题可以转化为LCA问题。下面说明如何在O(n)时间内实现这一转化。

我们将要将A的元素依次插入笛卡尔树C。每次插入都可能使树的形态发生变化。为了在O(N)的时间内完成整个插入过程,考虑C的右链,即根结点、根结点的右儿子、根结点的右儿子的右儿子……组成的链。注意这些元素的下标和值都是递增的。下标最大,即将要插入的元素A[i]一定是新树右链的最后一个元素。原来的右链中,值比A[i]大的元素在新树中不再属于右链,这些元素组成的链成为A[i]的左子树的右链;原来右链中的其它元素加上A[i]组成了新的右链。初看起来,寻找分界点的最佳方法是O(logN)时间的二分查找;但是对于整个过程来说,O(NlogN)的时间复杂度不是最优的。关键在于一旦一个元素比A[i]大,它就从右链中被永久地移除了。如果按照从后到前的顺序判断一个元素是否大于A[i],则每次插入的时间复杂度为O(k+1),k为本次插入中移除的右链元素个数。因为每个元素最多进出右链各一次,所以整个过程的时间复杂度为O(N)。

用一个栈结构维护右链元素的下标,上述过程可以很容易地实现。(见下面代码部分)

转化为约束RMQ

为了将LCA问题转化为约束RMQ,我们注意到任意树中两个结点u和v的LCA就是在一次从树根开始的深度优先搜索中,在u和v之间(包括回溯时)到达的结点中层数最小的一个。为了利用这一事实,我们建立三个数组:

E[1,2*N-1]:在一次深度优先搜索(恰好是树的一次欧拉环游)中每一步到达的结点。

L[1,2*N-1]:E中对应结点在树中的层数。

H[1,N]:每个结点在E中某一次出现的下标(不妨设为第一次)。

则对任意u和v,不妨设H[u]≤H[v](否则交换u和v),只要在L中找到[H[u],H[v]]中最小值的下标i,则E[i]就是u和v的LCA。注意到L满足约束RMQ的条件(相邻元素差的绝对值为1),这说明原来的LCA问题已经被转化为约束RMQ。转化过程显然能在O(N)时间内完成。

约束RMQ的解法

现在仍旧用A[0,N-1]表示问题中的数列,这里有|A[i]-A[i-1]|=1(i=1,2,...,N-1)成立。

将A分解为长度为l=[(log N)/2]的块。设A'[i]为第i块中的最小值,B[i]为该最小值的位置。A'[i]和B[i]的长度均为N/l, 所以用ST算法处理A'数组的时空复杂度均为O(N/l*log(N/l))=O(N/logN*(logN-logl))=O(N)。预处理之后,对任意多连续的块进行的查询都能在O(1)时间内实现。余下的问题是如何进行块内查询。

注意到对任意一块中的块内查询的结果有影响的唯一因素是块内每相邻两个元素间的“升降关系”构成的序列。因为每两个元素之间的关系只有两种(“+1”、“-1”),而块的长度又只有l=[(log N)/2],所以本质不同的块最多有2^I=O(sqrt N)种。对每种块中所有可能的块内查询预处理出答案的时空复杂度是O(sqrt N*l^2)=O(N)(这里的O(N)表示不超过线性时间)。预处理出所有块的“类型”,并用二进制数存储的时间复杂度是O(N)。

此后,每次查询可以分为两种情况:

1、块内查询,答案已经被预处理出,只要在数组中找到它即可。

2、块间查询,可以分解为2个块内查询,和一个A'上的RMQ,三者的时间复杂度都是O(1)。

综上,我们给出了一个预处理时间为O(n),查询时间为O(1)的在线RMQ算法。

文章内容摘抄于:

约束rmq_区间RMQ问题相关推荐

  1. 约束rmq_约束RMQ - osc_jor8x3el的个人空间 - OSCHINA - 中文开源技术交流社区

    不知道为什么网上找不到太多相关的资料,所以写一个小总结,并附有能用的代码,抛砖引玉. 约束RMQ,就是RMQ区间必须满足两项之差最大为1,采用ST表的话,这时候有O(n)建表,O(1)查询的优秀复杂度 ...

  2. 约束rmq_差分约束

    它们的差是不变的, 那么这个差分 约束系统中的所有不等式都不会被破坏. 差分约束系统的解法利用到了单源最短路径问题中的三角形不等式. 即对于 任何一条边 u -> v ,都有: d(v) < ...

  3. jzoj4817-square【区间RMQ,二分答案】

    正题 题目链接:https://jzoj.net/senior/#contest/show/2956/2 题目大意 n∗mn*mn∗m的010101矩阵,每次询问(x1,y1,x2,y2)(x1,y1 ...

  4. 牛客 - 骚区间(线段树+思维)

    题目链接:点击查看 题目大意:给出一个 1 ~ n 的排列 a ,现在规定骚区间当且仅当 a[ l ] 是 [ l , r ] 这段区间内的次小值,同时 a[ r ] 是 [ l , r ] 这段区间 ...

  5. Week8 :差分约束,拓扑排序和kahn,强连通图和kosaraju

    文章目录 差分约束 题目-区间选点II 输入输出 解题 代码 拓扑序列-kahn 题目-猫猫向前冲 输入输出 解题 代码 强连通图SCC-kosaraju 题目-班长竞选 输入输出 解题 代码 差分约 ...

  6. 基于相似性的动态区间多目标协同进化算法

    A Similarity-based Cooperative Co-evolutionary Algorithm  for Dynamic Interval Multi-objective Optim ...

  7. HDU6305: RMQ Similar Sequence 题解

    Description Chiaki has a sequence A={a1,a2,-,an}. Let RMQ(A,l,r) be the minimum i (l≤i≤r) such that ...

  8. QAQorz的训练记录

    感觉还是该从今天开始记下来 5.8日查询 870(查询系统) + 100(洛谷) + 100(牛客) = 1070题, 去重按1000题算 5.8 牛客寒训营 3F 双向搜索+处理前后缀积 牛客寒训营 ...

  9. Codeforces Good Bye 2016 题解

    好久没有fst题了...比赛先A了前4题然后发现room里有人已经X完题了没办法只能去打E题,结果差一点点打完...然后C题fst掉了结果就掉rating 了...下面放题解 A. New Year ...

最新文章

  1. Nutanix 将社区版代码带入云中
  2. SpringMVC实现简单的图片上传DEMO
  3. 嵌入式基础之----C语言
  4. java之简单的Callback使用总结
  5. php 收缩栏,HTML5每日一练之details展开收缩标签的应用
  6. Java 进阶之路:异常处理的内在原理及优雅的处理方式
  7. 2.6的网络数据包时间戳
  8. cms文章 mysql存储,帝国CMS万能标签调用随机文章的方法
  9. linux软件抗干扰,解决asterisk下使用misdn时被SELinux干扰导致权限不足的问题
  10. 基于遗传算法优化极限学习机预测及其MATLAB实现-附代码
  11. 欢迎清风艾艾在ITPUB博客安家!
  12. 微信公众号考试成绩查分系统
  13. windows server 2012 安装 VC++ 安装失败0x80240017解决方法
  14. Lab颜色空间及其应用
  15. 读写Excel工具类ExcelUtil
  16. ae中计算机打字预设,Typewriter Pro(AE电脑打字动画特效预设)
  17. 【操作系统】第五章——虚拟内存技术
  18. 历尽千帆,归来仍少年
  19. iOS开发笔记--超全!iOS 面试题汇总
  20. sns.boxplot()简单用法

热门文章

  1. CMMI三级认证怎么费用的?
  2. Linux基础(五):系统运行级别
  3. oracle 10安装失败,安装oracle 10失败
  4. 下载Windows原版镜像,这里下载,何必MSDN呢
  5. php微信支付结果通知接收,PHP接收微信支付结果通知 notify
  6. Direct2D简介
  7. 2020.11.2--AE--时间轴变换功能、关键帧、动效的基本操作
  8. 20180711 F-Divisions
  9. 学习设计模式之中介者模式
  10. 2021最新港澳台华侨生联考艺术政策解析/景于行港澳台华侨联考