http://poj.org/problem?id=3264
问题概述: 先输入n个数,然后输入m个指令,每个指令(a,b)表示求出区间[a,b]中的最大值与最小值的差
输入样例: 对应输出:
6 3 6 3 0
1 7 3 4 2 5
1 5
4 6
2 2
RMQ问题:查询区间最值,复杂度nlogn,每次查询没有复杂度,相对线段树更快
思路:动态规划,先花nlogn的时间预处理,dp[i][j]表示区间[i,i+2^j-1]的最值
→初始化∑idp[i][0] = a[i]→状态转移dp[i][j] = dp[i][j-1]+dp[i+(1<<(j-1))][j-1]
对于每次查询[a,b]区间的最值
→ans = max/min(dp[a][p], dp[b-(1<<p)+1][p]),其中p满足2^p最大且不超出区间长度
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct
{
int max;
int min;
}Line;
Line dp[50005][22];
int a[50005];
int main(void)
{
int n, m, i, j, c, d, p, ans;
while(scanf("%d%d", &n, &m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d", &a[i]);
for(i=1;i<=n;i++)
dp[i][0].max = dp[i][0].min = a[i];
for(j=1;(1<<j)<=n;j++)
{
for(i=1;i+(1<<j)-1<=n;i++)
{
dp[i][j].max = max(dp[i][j-1].max, dp[i+(1<<(j-1))][j-1].max);
dp[i][j].min = min(dp[i][j-1].min, dp[i+(1<<(j-1))][j-1].min);
}
}
for(i=1;i<=m;i++)
{
scanf("%d%d", &c, &d);
p = 0;
while((1<<p)<=d-c+1)
p++;
p--;
ans = max(dp[c][p].max, dp[d-(1<<p)+1][p].max)-min(dp[c][p].min, dp[d-(1<<p)+1][p].min);
printf("%d\n", ans);
}
}
return 0;
}