Poj 3264 Balanced Lineup RMQ模板
题目链接:
题目描述:
给出一个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 }
本文为博主原创文章,未经博主允许不得转载。