Poj 3264 Balanced Lineup RMQ模板

题目链接:

  Poj 3264 Balanced Lineup

题目描述:

  给出一个n个数的序列,有q个查询,每次查询区间[l, r]内的最大值与最小值的绝对值。

解题思路:

  很模板的RMQ模板题,在这里总结一下RMQ:RMQ(Range Minimum/Maximum Query) 即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。

  RMQ有三种求法:1:直接遍历查找,炒鸡暴力;

           2:线段树也可以解决这一类问题;

           3:ST(Sparse Table)算法:在线处理RMQ问题,可以做到O(n*log(n))内预处理,O(1)内查询到所要结果。

  对于ST(Sparse Table)算法,预处理的时候用的是DP思想,用一个二维数组dp[i][j]记录区间[i,i+2^j-1] (持续2^j个)区间中的最小值(其中dp[i,0] = a[i])

  对于任意的一组(i,j),dp[i][j] = min{dp[i][j-1],dp[i+2^(j-1)][j-1]}来使用动态规划计算出来。最优美的地方还在与查询的时候,对于区间[m, n],可以找到一个k,k满足 n-m+1 < 2^(k+1),然后ans = min {dp[m][m+2^k-1],  [n-2^k+1][n]},区间[m,m+2^k-1]和[n-2^k+1,n]内的最值我们是预处理过的,所以在O(1)的时间内就可以找到ans咯。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 50010;
 8 int dmin[maxn][18], dmax[maxn][18];
 9 int arr[maxn];
10 
11 void RMQ_init (int n)
12 {
13     for (int i=0; i<n; i++)
14         dmin[i][0] = dmax[i][0] = arr[i];
15 
16     for (int j=1; (1<<j)<=n; j++)
17         for (int i=0; i+(1<<j)-1<n; i++)
18         {
19             dmin[i][j] = min (dmin[i][j-1], dmin[i+(1<<(j-1))][j-1]);
20             dmax[i][j] = max (dmax[i][j-1], dmax[i+(1<<(j-1))][j-1]);
21         }
22 }
23 int solve (int a, int b)
24 {
25     int x = 0;
26     while (1<<(x+1) <= b-a+1)    x++;
27     int Max = max (dmax[a][x], dmax[b-(1<<x)+1][x]);
28     int Min = min (dmin[a][x], dmin[b-(1<<x)+1][x]);
29     return Max - Min;
30 }
31 
32 int main ()
33 {
34     int n, q, a, b;
35     while (scanf ("%d %d", &n, &q) != EOF)
36     {
37         for (int i=0; i<n; i++)
38             scanf ("%d", &arr[i]);
39         RMQ_init( n );
40         while (q --)
41         {
42             scanf ("%d %d", &a, &b);
43             printf ("%d\n", solve(a-1, b-1));
44         }
45     }
46     return 0;
47 }

 

posted @ 2015-09-05 18:53  罗茜  阅读(170)  评论(0编辑  收藏  举报