范围最小值问题 (Range Minimum Query,RMQ)
给出一个n个元素的数组A1,A2,…,An
设计一个数据结构,支持查询操作Query(L,R):计算min {AL,AL+1,..AR}.
思路:令d(i,j)表示从i开始的,长度为2^j的一段元素中的最小值,用递推的方法计算d(i,j),d(i,j) = min{d(i,j-1),d(i+2^(j-1), j-1)}
查询操作,令k为满足2^k<=R-L+1的最大整数,则以L开头、以R结尾的两个长度为2^k的区间合起来覆盖查询区间[L, R].
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
void RMQ_init(const vector<int>& A) {
int n = A.size();
for (int i = 0; i < n; i++) {
d[i][0] = A[i];
}
for (int j = 1; (1<<j) <= n; j++) {
for (int i = 0; i + (1<<j) - 1 < n; i++) {
d[i][j] = min(d[i][j-1], d[i+(1<<(j-1))][j-1]);
}
}
}
int RMQ(int L, int R) {
int j = 0;
while ((1<<(j+1)) <= R-L+1) {
j++;
}
return min(d[L][j], d[R-(1<<j)+1][j]);
}