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]);

}

你可能感兴趣的:(MQ)