福建农林大学 FAFU poj也有一题和这题差不多的,可以去尝试看看
http://acm.fafu.edu.cn/problem.php?id=1272
RMQ poj 3264 Balanced Lineup
//poj 3264 Balanced Lineup //RMQ //用RMQ求出最大值和最小值相减即可,具体看一下代码 //学RMQ可以看着个博客http://blog.csdn.net/ice2013/article/details/7545143 //写的挺不错的 //预处理, //动归求出dp_max[i][j]和dp_min[i][j],dp表示从i开始的2^j个数中的最值, //2^j一定是偶数,所以把它分为 [i,i+2^(j-1)-1]和[i+2^(j-1), i+2^j -1]这两个区间, //则dp[i][j]即从这两个区间得出,即dp[i][j] = max(dp[i][1<<(j-1)], dp[i+(1<<(j-1)][j-1]) //询问[a,b]时先求出tmp = log(b-a+1)/log(2.0) //然后求max(dp[a][tmp], dp[b-(1<<tmp) + 1][tmp]) //注意:动归过程中要注意i+(1<<j)-1 <= n,询问时记得 //dp[b - (1<<tmp) + 1][tmp]前面那个要加 1 #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namespace std; #define comein freopen("in.txt", "r", stdin); #define N 50005 #define INF 1<<30 #define eps 1e-5 int dp_max[N][20], dp_min[N][20]; void init(int n_cow) { //n_cow可以表示成2 的几次方,换底公式 int index = log(n_cow * 1.0) / log(2.0); for(int j = 1; j <= index; ++j) { //i ~ i+(1<<j)-1 之间有 i+(1<<j)-1 - i + 1 即 1<<j个数,包括i for(int i = 1; i + (1<<j) - 1 <= n_cow; ++i) { //dp[i][j]表示从i起 2^j个数,i ~ i+(2^j)-1 这个区间的最值 //如dp[3][2] 表示 3 ~ 6,从3起有2^2个数,因为这样区间长度都为偶数个 //所以把 区间分为 i~ i+(2^j-1)-1 和 i+(2^j-1)-1 ~ i+(2^j)-1这两个区间 //长度都为 2^(j-1) 个数, 所以dp[i][j]的记录的最值即为dp[i][j-1] 和 //dp[i + (2^(j-1))][j-1]这两个部分的最值 dp_max[i][j] = max(dp_max[i][(j-1)], dp_max[i + (1<<(j-1))][j-1]); dp_min[i][j] = min(dp_min[i][(j-1)], dp_min[i + (1<<(j-1))][j-1]); } } } int RMQ(int from, int to) { //假如我们需要查询的区间为(i,j), //因为这个区间的长度为j - i + 1,所以我们可以取k=log2( j - i + 1), //则有:RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。 int index = log((to - from + 1) * 1.0) / log(2.0); int mx = max(dp_max[from][index], dp_max[to - (1<<index) + 1 ][index]); int mn = min(dp_min[from][index], dp_min[to - (1<<index) + 1 ][index]); return mx - mn; } int main() { int n_cow, n_query; while(scanf("%d%d", &n_cow, &n_query) != EOF) { for(int i = 1; i <= n_cow; ++i) { int heigh; scanf("%d", &heigh); //从第i个起的 2^0 个数中的最大值和最小值 dp_max[i][0] = dp_min[i][0] = heigh; } init(n_cow); while(n_query--) { int from, to; scanf("%d%d", &from, &to); if(from > to) { from ^= to; to ^= from; from ^= to; } printf("%d\n", RMQ(from, to)); } } return 0; }