POJ-3264 Balanced Lineup RMQ
直接维护好两个数组就可以了,每次访问得到区间的最小值和最大值。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; int N, M, seq[50005], Min[50005][20], Max[50005][20]; void Minbuild() { int LIM = (int)log2(double(N)); for (int i = 1; i <= N; ++i) { Min[i][0] = seq[i]; } for (int j = 1; j <= LIM; ++j) { for (int i = 1; i+(1<<j)-1 <= N; ++i) { Min[i][j] = min(Min[i][j-1], Min[i+(1<<j-1)][j-1]); } } } void Maxbuild() { int LIM = (int)log2(double(N)); for (int i = 1; i <= N; ++i) { Max[i][0] = seq[i]; } for (int j = 1; j <= LIM; ++j) { for (int i = 1; i+(1<<j)-1 <= N; ++i) { Max[i][j] = max(Max[i][j-1], Max[i+(1<<j-1)][j-1]); } } } int Maxquery(int l, int r) { int k = (int)log2(double(r-l+1)); return max(Max[l][k], Max[r-(1<<k)+1][k]); } int Minquery(int l, int r) { int k = (int)log2(double(r-l+1)); return min(Min[l][k], Min[r-(1<<k)+1][k]); } int main() { int l, r; while (scanf("%d %d", &N, &M) == 2) { for (int i = 1; i <= N; ++i) { scanf("%d", &seq[i]); } Minbuild(), Maxbuild(); for (int i = 1; i <= M; ++i) { scanf("%d %d", &l, &r); printf("%d\n", Maxquery(l, r) - Minquery(l, r)); } } return 0; }