转载地址:http://blog.csdn.net/niushuai666/article/details/7401403
题目链接:http://poj.org/problem?id=3264
题目大意:
一个农夫有N头牛,每头牛的高度不同,我们需要找出最高的牛和最低的牛的高度差。
解题思路:
我是用RMQ写的。
N为50000,Q为200000,如果我们暴力的话,需要50000*200000=10000000000,需要25s左右.所以我们需要高效的算法,而RMQ正好解决的就是区间最值问题,复杂度为nlogn,这样就可以了。
另外还可以用线段树,因为线段树的别名就是区间树。segment tree
代码如下:
- #include<iostream>
- #include<cstring>
- #include<cstdio>
- #include<climits>
- #include<cmath>
- #include<algorithm>
- using namespace std;
- const int N = 50005;
- int FMAX[N][20], FMIN[N][20];
- void RMQ(int n)
- {
- for(int j = 1; j != 20; ++j)
- {
- for(int i = 1; i <= n; ++i)
- {
- if(i + (1 << j) - 1 <= n)
- {
- FMAX[i][j] = max(FMAX[i][j - 1], FMAX[i + (1 << (j - 1))][j - 1]);
- FMIN[i][j] = min(FMIN[i][j - 1], FMIN[i + (1 << (j - 1))][j - 1]);
- }
- }
- }
- }
- int main()
- {
- int num, query;
- int a, b;
- while(scanf("%d %d", &num, &query) != EOF)
- {
- for(int i = 1; i <= num; ++i)
- {
- scanf("%d", &FMAX[i][0]);
- FMIN[i][0] = FMAX[i][0];
- }
- RMQ(num);
- while(query--)
- {
- scanf("%d%d", &a, &b);
- int k = (int)(log(b - a + 1.0) / log(2.0));
- int maxsum = max(FMAX[a][k], FMAX[b - (1 << k) + 1][k]);
- int minsum = min(FMIN[a][k], FMIN[b - (1 << k) + 1][k]);
- printf("%d\n", maxsum - minsum);
- }
- }
- return 0;
- }