查看“︁范围最值查询”︁的源代码
←
范围最值查询
跳转到导航
跳转到搜索
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
{{noteTA|G1=IT}} {{redirect|RMQ|台中清泉崗機場的IATA代碼|台中清泉崗機場}} '''范围最值查询'''({{lang-en|Range Minimum Query}}),是针对[[数据集]]的一种条件查询。若给定一个数组<math>A[1, n]</math>,范围[[最值]]查询指定一个范围条件<math>i</math>到<math>j</math>,要求取出<math>A[i, j]</math>中最大/小的元素。 若<math>A = [3, 5, 2, 5, 4, 3, 1, 6, 3]</math>,条件为<math>[3, 8]</math>的范围最值查询返回1,它是子数组<math>A[3, 8] = [2, 5, 4, 3, 1, 6]</math>中最小的元素。 通常情况下,数组A是静态的,即元素不会变化,例如插入、删除和修改等,而所有的查询是以[[在线]]的方式给出的,即预先并不知道所有查询的参数。 RMQ问题有预处理<math>O(n)</math>之后每次查询<math>O(1)</math>的算法<ref>Fischer, Johannes; Heun, Volker (2007), "A New Succinct Representation of RMQ-Information and Improvements in the Enhanced Suffix Array.", Proceedings of the International Symposium on Combinatorics, Algorithms, Probabilistic and Experimental Methodologies, Lecture Notes in Computer Science, 4614, Springer-Verlag, pp. 459–470, [http://dx.doi.org/10.1007%2F978-3-540-74450-4_41 doi:10.1007/978-3-540-74450-4_41]</ref>。 范围最值查询问题(RMQ)与[[最近公共祖先 (图论)|最近公共祖先]](LCA)问题有直接联系,它们可以互相转化。RMQ的算法常常应用在严格或者近似子串匹配等问题的处理中。 == 算法 == === Sparse Table === 建立一个二维数组 <math>F[1 \dots N][0 \dots O(\log_2 N)]</math> 的整数值。 在这个数组中 <math>F[i][j]</math> 表示范围 <math>[i, i+2^j-1]</math> 中的最大值(例如 <math>[2, 5]</math> 中的最大值被计为 <math>F[2][2]</math>)。 建立数组的过程可以在 <math>O(N \log N)</math> 时间内完成。具体算法类似于动态规划。以下是 C++ 语言描述的代码,数组约定从 0 开始:<syntaxhighlight lang="c++"> void Initialise(vector<int> &Array) { int Length = (int)Array.size(); // 长度为 0 时,表示数据自身。 for (int i = 0; i < Length; ++i) F[i][0] = Array[i]; for (int j = 1; (1 << j) <= Length; ++j) for (int i = 0; i + (1 << j) - 1 < Length; ++i) F[i][j] = min( F[i][j - 1], F[i + (1 << (j - 1))][j - 1] ); // 分成长度相等的两段 } </syntaxhighlight>当我们需要计算一个区间中的最大值(例如 <math>[3, 8]</math> 时),我们先求出这个区间的长度(即 8 - 3 + 1 = 6)。 然后我们算出不大于它的最大 <math>2^k</math> 值的指数(即 2)。我们要查询分别以 3 开头,和以 8 结尾的两个长度为 <math>2^2</math> 的区间的最大值。 显然 <math>F[3][2]</math> 和 <math>F[5][2]</math> 也就是(<math>[3, 6]</math> 和 <math>[5, 8]</math>)的最大值就是 <math>[3,8]</math> 的最大值。查询的时间是常数,代码如下:<syntaxhighlight lang="c++"> int Query(int Left, int Right) { int i = 0; while (1 << (i + 1) <= Right - Left + 1) ++i; return min( F[Left][i], F[Right - (1 << i) + 1][i] ); } </syntaxhighlight>程序预处理的时间复杂度是 <math>O(N \log N)</math>的,单次询问的时间复杂度是<math>O(1)</math>的。整个程序的空间复杂度是<math>O(N \log N)</math>。 === Method of Four Russians === {{Tsl|en|Method of Four Russians}}先对数组进行分块,再预处理出每个块里的ST表,以及每个块的最值构成的数组的ST表。然后每次查询时,只需算出中间连续几个块的最小值与两边不完整的块的最小值的最小值。程序预处理的时间复杂度是 <math>O(N \log\log N)</math>的,单次询问的时间复杂度是<math>O(1)</math>的。整个程序的空间复杂度是<math>O(N \log\log N)</math>。还可以再优化,使预处理的时间复杂度是 <math>O(N)</math>的,单次询问的时间复杂度是<math>O(1)</math>的,空间复杂度是<math>O(N)</math>。{{sfn|Arlazarov|Dinic|Kronrod|Faradzev|1970}} == 数据结构 == 如果使用线段树等数据结构,则可以做到预处理的时间复杂度是 <math>O(N \log N)</math>,单次询问的时间复杂度是<math>O(\log N)</math>。整个程序的空间复杂度是<math>O(N)</math>。优点是可以支持动态修改。 == 应用 == 在Fischer和Heun(2007)中可以找到一些应用。<ref name=":0">{{cite conference |last1=Fischer |first1=Johannes |last2=Heun |first2=Volker |year=2007 |title=Combinatorics, Algorithms, Probabilistic and Experimental Methodologies |conference=Proceedings of the International Symposium on Combinatorics, Algorithms, Probabilistic and Experimental Methodologies |series=LNCS |publisher=Springer |volume=4614 |pages=459–470 |doi=10.1007/978-3-540-74450-4_41 |isbn=978-3-540-74449-8}}</ref>{{Rp|3}} === 计算树中的最近公共祖先 === 范围最值查询可被用于解决最近公共祖先问题<ref>{{cite journal |last1=Bender |first1=Michael A. |last2=Farach-Colton |first2=Martín |last3=Pemmasani |first3=Giridhar |last4=Skiena |first4=Steven |last5=Sumazin |first5=Pavel |year=2005 |title=Lowest common ancestors in trees and directed acyclic graphs |url=http://www.cs.sunysb.edu/~bender/pub/JALG05-daglca.pdf |journal=Journal of Algorithms |volume=57 |issue=2 |pages=75–94 |doi=10.1016/j.jalgor.2005.08.001 |access-date=2022-08-23 |archive-date=2012-01-06 |archive-url=https://web.archive.org/web/20120106011949/http://www.cs.sunysb.edu/~bender/pub/JALG05-daglca.pdf |dead-url=no }}</ref><ref>{{cite conference |last1=Bender |first1=Michael |last2=Farach-Colton |first2=Martín |year=2000 |title=LATIN 2000: Theoretical Informatics |conference=LATIN 2000: Theoretical Informatics |series=LNCS |publisher=Springer |volume=1776 |pages=88–94 |doi=10.1007/10719839_9 |isbn=978-3-540-67306-4}}</ref>。有根树S中的节点v与w的最近公共祖先是在从根到w和v的路径上最深的公共节点u(其可能是v或w)。 Gabow, Bentley和Tarjan(1984)表明,最近公共祖先问题可以在线性时间内规约到范围最值查询问题。由此可见,与范围最值查询问题一样,最近公共祖先问题可以在常数时间内进行单次查询,并仅使用线性空间<ref name=":0" />。 == 参考资料 == {{reflist}} [[Category:搜尋演算法]]
该页面使用的模板:
Template:Cite conference
(
查看源代码
)
Template:Cite journal
(
查看源代码
)
Template:Lang-en
(
查看源代码
)
Template:NoteTA
(
查看源代码
)
Template:Redirect
(
查看源代码
)
Template:Reflist
(
查看源代码
)
Template:Rp
(
查看源代码
)
Template:Sfn
(
查看源代码
)
Template:Tsl
(
查看源代码
)
返回
范围最值查询
。
导航菜单
个人工具
登录
命名空间
页面
讨论
不转换
查看
阅读
查看源代码
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
工具
链入页面
相关更改
页面信息