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