范围最值查询问题(RMQ)与最近公共祖先 (图论)(LCA)问题有直接联系,它们可以互相转化。
RMQ的算法常常应用在严格或者近似子串匹配等问题的处理中。
RMQ问题
点这里看在线与离线的定义.
RMQ的所有查询都是以在线的方式给出的,即原先并不知道所有查询的参数。
如果不预处理,每次询问都才进行处理,那么算法的复杂度O(qn)是很高的。所以我们要预处理一下,而RMQ问题有 通过预处理O(n)使每次查询为O(1) 的算法
。
主要方法及复杂度:
1、朴素(即搜索),O(n) - O(qn) online。
2、线段树,O(n)-O(qlogn) online。
3、ST(实质是动态规划),O(nlogn)-O(q) online。
4、RMQ标准算法:先规约成LCA(Lowest Common Ancestor),再规约成约束RMQ,O(n)-O(q) online。
ST 算法 (实质是动态规划)
这是几个要点。
st[i][j] 表示以 i 开头 i + 2j 结尾的区间的最值。
初态:st[i][0] = a[i];
状态转移: st[i][j] = min/max (st[i][j-1], st[i+(1<<(j-1))][j-1]);
这两篇博文讲得很好,看他的就OK了。
https://siukwan.sinaapp.com/?p=830#comment-11392
https://criskaa.github.io/2016/10/01/RMQ(ST算法)/
个人理解
这个算法,预处理时通过dp做到全覆盖,询问的时候则将区间分成两个有重叠区域的部分,取最值。
笛卡尔树 LCA
首先根据原数列,建立笛卡尔树,从而将问题在线性时间内规约为LCA问题。LCA问题可以在线性时间内规约为约束RMQ,也就是数列中任意两个相邻的数的差都是+1或-1的RMQ问题。约束RMQ有O(n)-O(1)的在线解法,故整个算法的时间复杂度为O(n)-O(1)。
等学了图论的LCA再来补充
代码
#include<bits.stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int n, m;
int a[maxn];
int stmin[maxn][100];
void init()
{
for (int i = 0; i < n; ++i) // 长度为 0 时,表示数据自身。
stmin[i][0] = a[i];
for (int j = 1; (1 << j) <= n; ++j)
for (int i = 0; i + (1 << j) - 1 < n; ++i)
st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); // 分成长度相等的两段
}
int query(int l, int r)
{
int x = (int)(log(double(r - l + 1)) / log(2.0));
return min(stmin[l][x], stmin[r - (1 << x) + 1][x]);
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
init();
int l, r;
for(int i = 0; i < m; i++)
{
scanf("%d %d", &l, &r);
printf("%d %d\n", queru(l, r);
}
return 0;
}
参考来源
百度百科
https://baike.baidu.com/item/rmq/1797559?fr=aladdin
wiki百科
https://zh.wikipedia.org/wiki/范围最值查询#cite_note-1
博客
https://siukwan.sinaapp.com/?p=830
在线算法与离线算法
wiki上的定义
在线算法
是一种处理输入数据的独特形式,其演算过程中并不要求所有输入数据在算法开始运始之一刻即完备,反而可对逐步输入的数据加以处理并在输入完最后一项数据之后输出运算结果。
离线算法
是假设输入数据在运算开始前已完备。
举例与解释:
插入排序是在线算法,就像打扑克发牌的时候,对于那些发给你的牌,你可以一张一张拿起来(算法执行的过程中有数据输入),然后插入你手上拿着的牌里面。
选择排序是离线算法,因为选择排序每次会选择最值然后进行交换,如果边执行边输入(且不说如何做到),答案极可能会出错。所以选择排序是离线算法,输入完成后,然后执行到算出答案。
注意:
对于很多问题,在线算法的性能比不上离线算法(即无法获取最优的结果)。
如果对于同一个问题的在线算法和最优化的离线算法的性能比率是有界的,那么这个在线算法则是有竞争力的算法。(大意就是这样的在线算法个好算法)
并非所有在线算法都有与之对应的离线算法。