RMQ算法(Range Minimum/Maximum Query)

如果让你一串数组,让你查询在一个区间[ L, R ] 的最大值或者最小值,很容易想到遍历一下,时间复杂度是O( n ),但是如果你查询m次呢(m 约1000000次作用),还能用遍历的方法么,显然是不能,所以就可以用到RMQ算法,时间复杂度是O( n * log n),还是比直接遍历节约时间。RMQ算法又叫做在线查找,为什么叫在线查找,因为经过预处理,所有的范围最大值,或者最小的值都已经找到了,直接查找就OK了,查找的时间复杂度是O(1)。

1.神马是RMQ算法?

      RMQ算法是不是听起来非常的高大尚,其实用起来也非常的略屌。下面是RMQ的科学定义:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。

 2.RMQ顺发是什么思想?

    RMQ是根据动态规划的思想,F[ i, j] = min (F[ i, j - 1], F [i + (1<<(j - 1)), j-1])。不断地更新达到想要的数据, F[ i, j]用i来储存比较其距离i的位置1<

 3.RMQ算法如何的预处理?

        先上代码:

void rmq(int m){
     for(int i = 1; i <= m; i++)
        mn[i][0] = a[i];
     for(int j = 1; (1 << j) <= m; j++){
        for(int i = 1; (i + (1<

这串代码看不懂很正常,接下来我来举个例子:3  5  1  10  12

用一个数组F[ i, j ]来不断更新结果,首先是F [ i, 0 ] = a[i], 这是原始赋值,开始第一次遍历 F[ 1,1] = min (F[ 1, 0], F [1 + 1, 0]= 5, F[ 2,1] = min (F[ 2, 0], F [2 + 1, 0]) = 5, F[ 3,1] = min (F[ 3, 0], F [3 + 1, 0]) = 10, F[ 4,1] = min (F[ 4, 0], F [4 + 1, 0]) = 12. 第二次遍历,F[ 1,2] = min (F[ 1, 1], F [3, 1]) = 5, F[ 2,2] = min (F[ 2, 1], F [4, 1]) = 12。然后结束了,其实就是先俩来比较,让后用左边的去存储两个数中最大的,然后用四个比较从中间分成两份,因为只需比较跟他差一个位置的就行,因为例题数据比较小,所以也就更新到四个数之间的比较就结束了,如果数据比较多的话,还可以接着更新,八个比较,分成两份,只需比较与他差三个位置的数进行比较就可以了。

4.如何查找?

因为预处理之后,很多范围的最大值或者最小值都应经更新完了,但是这些跟新的只是距离他左侧范围L的位置距离是2^n,但是很多时候查询不可能就是你更新的范围,所以就有一种覆盖的思想,虽然有的地方会会重复但是没有影响。计算公式:k = log2(r - l + 1), min = min( F[ l, k], F [ r - (1<

5.例题

下面的例题使纯练习的题,没有任何的弯路,就是这就测试,你敲的代码是不是正确的。

洛谷   P1816 忠诚 

链接:https://www.luogu.org/problemnew/show/P1816

#include
#include
#include
#include
#include
using namespace std;
#define N 100010
int a[N], mn[N][100], b[N];
int val;
void rmq(int m){
     for(int i = 1; i <= m; i++)
        mn[i][0] = a[i];
     for(int j = 1; (1 << j) <= m; j++){
        for(int i = 1; (i + (1<>n>>m;
    int cn = 0;
    for(int i = 1; i <= n; i++){
        cin>>a[i];
    }
    rmq(n);
    while(m--){
        cin>>l>>r;
        Query(l, r);
        b[cn] = val;
        cn++;
    }
    for(int i = 0; i < cn; i++)cout<

Poj   Balanced Lineup

链接:http://poj.org/problem?id=3264

#include
#include
#include
#include
#include
using namespace std;
#define N 50010
int ma[N][100], mn[N][100];
int a[N];
int RMQ(int n){
    int i, j;
    for(i = 1; i <= n; i++){
        mn[i][0] = ma[i][0] = a[i];
    }
    for(j = 1; (1<

 

你可能感兴趣的:(算法)