// 在教室上自习的时候瞪着书瞪了近一个小时没搞明白在说些什么,回家后自己敲了一般发现==呵呵这不就是dp吗。。。
关于RMQ
RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题
ST算法思路
既然是dp==那就先扔出转移方程
d[i][j] = min( d[i][j-1], d[i+( 1<<(j-1) )][j-1] )
// d[i][j]表示从i开始,长度为(1<<j)的一段元素中的最小值
是一个二维dp,状态总数为(n log n)。
将d数组构建完毕后,便可以直接查询了。
预处理代码
void RMQ_init(const int* a, int n) {
for(int i = 0; i < n; i++)
d[i][0] = a[i]; //区间[i, i]的最小值为i;
for(int j = 1; (1<<j) <= n; j++) //枚举区间长度
for(int i = 0; i + (1<<j) - 1 < n; i++) //枚举起点,当终点大于n时,停止枚举;
d[i][j] = min( d[i][j-1], d[i+(1<<(j-1))][j-1] ); //状态转移
} //st算法预处理
st算法的查询
int RMQ(int l, int r){
int k = 0;
while( (1<<(k+1)) <= r-1+1 ) k++; //找到满足 (1<<k)<=区间长度 的k的最大值 如果(1 << (k+1)) <= r-l+1 那么k还能加一;
return min(d[l][k], d[r - (1<<k) + 1][k]); //l>(r - (1<<k) + 1)没问题,因为取最小值时重合区间并不影响。
}