Description
For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.
Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.
Input
Output
Sample Input
6 3 1 7 3 4 2 5 1 5 4 6 2 2
Sample Output
6 3 0
这道题是自己做的第一道RMQ题,RMQ算法不难理解,但其中有很多细节需要牢固记忆。
1. 进行RMQ时,区间长度 j ,for(j=1;(1<<j)<=N;++j )
2.进行RMQ时,下标 i ,for(int i=0;i+(1<<j)-1<N;++i)
3.不要忘记求区间范围时,给左右边界同时-1,以转换为下标。
4.最后多做简单的优化,如可以不用赋初值时,不用memset 优化,可以减少一半的时间消耗
#include<stdio.h> #include<iostream> #include<cstring> #include<math.h> using namespace std; const int inf = 0x3f3f3f3f; int high[50010]; int Rmq[50010][20]; int rmq[50010][20]; int N, Q; int max(int a, int b) { return a > b ? a : b; } int min(int a, int b) { return a < b ? a : b; } void RMQ() { for (int i = 0; i < N; ++i) { rmq[i][0] = high[i]; Rmq[i][0] = high[i]; } for (int j = 1; (1 << j)<= N; ++j) { for (int i = 0; i + (1 << j)-1 < N; ++i) { Rmq[i][j] = max(Rmq[i][j - 1], Rmq[i + (1 << (j - 1))][j - 1]); rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]); } } } void query(int a, int b) { int k = log(b - a + 1.0)/log(2.0); a--; b--; int maxx = max(Rmq[a][k], Rmq[b - (1 << k) + 1][k]); int minn = min(rmq[a][k], rmq[b - (1 << k) + 1][k]); cout << maxx - minn << endl; } int main() { //freopen("in.txt","r",stdin); while(cin >> N >> Q) { for (int i = 0; i < N; ++i) cin >> high[i]; memset(rmq, inf, sizeof(rmq)); memset(Rmq, -inf, sizeof(Rmq)); RMQ(); for (int j = 1; j <= Q; ++j) { int a, b; cin >> a >> b; query(a, b); } } return 0; //system("pause"); }