1、首先要了解一下RMQ的概念:
RMQ (Range Minimum/Maximum Query)问题是指:
对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。-----------摘自百度百科
2、求取最值的方法
(1)暴力,时间复杂度O(n^2)
(2)ST表,首先进行预处理O(nlogn)之后单次查询O(log(r-l))
3、分析ST方法
核心代码块理解:dp【i,j】表示从第i个数开始连续2^j个数中的最值
/* 以求最大值为例 */ const int maxn = 105; int dp[maxn][len];// len的条件:2^len > maxn 即可 int a[maxn]; int n; //数组的长度 void rmq_init() { for(int i = 1; i <= n; i++) { dp[i][0] = a[i];//从第i个数开始之后的2^0 = 1个数的最值就是其本身 } for(int j = 1; (1<<j) <= n; j++) //往后的长度不能超n { for(int i = 1; (i+(1<<j)-1) <= n; i++) //第i个数之后的2^j个数,其长度不能超n { dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]); /*重点解释一下这条语句: 从第i个数开始,在2^j个数中求最值,可以将2^j范围拆成两个2^(j-1) 即第一段:a[i]~~a[i+(2^(j-1))] 第二段:a[i+(2^(j-1)]~a[i+2^j] */ } } } int rmq_max(int l, int r) {
int k = 0; //k就是要划分的一半区间的幂级数 while( (1<<(k+1)) <= r - l + 1) { k++; } return max(dp[l][k], dp[r-(1<<k)+1][k]); }
安利一篇博客,讲的很是透彻