RMQ

1.定义

    RMQ,Range Min/Max Query,区间最小/大值查询。

    对于数组A,

    定义Query(i,j)= min {Ai,Ai+1,…Aj},即为RMQ问题。

    算法思想

    使用Tarjan的Sparse-Table算法,简称ST算法。

    令d(i,j)表示从i开始的,长度为2^j的区间中的最小值,则用递推的方式可得:

    d(i,j) = min{d(i,j-1),d(i+2^(j-1),j-1)}

2.API

l initRMQ()

初始化ST表;

使用DP递归的方式初始化d(i,j)

void RMQ_Init()
{
    for (int i = 1; i <= n; i++)
    {
        d[i][0] = array[i];
    }

    //d(i,j) = min{d(i,j-1),d(i+2^(j-1),j-1)}
    for (int j = 1; (1 << j) <= n; j++)
    {
        for (int i = 1; i + j - 1 <= n; i++)
        {
            d[i][j] = Math.Min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
        }
    }
}

l queryRMQ(L,R)

查询区间[L,R]的最值

//RMQ(A,i,j) = M[i][k] (A[M[i][k]]<A[M[j-2^k+1][k]])
/// <summary>
/// 寻找区间 2^k <= R-L+1内的最小值
/// </summary>
/// <param name="L"></param>
/// <param name="R"></param>
/// <returns></returns>
public int GetRMQ(int L, int R)
{
    int k = 0;
    while ((1 << (k + 1)) <= R - L + 1) k++;//保证最大区间覆盖
    return Math.Min(d[L][k], d[R - (1 << k) + 1][k]);
}
原文地址:https://www.cnblogs.com/pengzhen/p/4373399.html