题意:给N只金宝的长度,Q次查询,给出区间[A, B]上最大值和最小值之差。
线段树入门.
线段树比较灵活,写法都是随心而为,不必拘泥于实现,抓住其更本质的数据结构思想即可。
//segment tree
//all bounds are tight. for bound (A, B), it means [A, B]
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX = 50007;
int height[MAX];
struct node {
//int left, right;
int min, max;
} a[MAX << 2];
int N, Q;
inline int L(const int& x) {
return x << 1;
}
inline int R(const int& x) {
return x << 1 | 1;
}
void build(int root, int left, int right) {
//printf("build (%d, %d, %d)\n", root, left, right);
//getchar();
if (left > right) return;
//a[root].left = left, a[root].right = right;
if (left == right) {
a[root].min = a[root].max = height[left];
} else {
int mid = (left + right) >> 1;
build(L(root), left, mid);
build(R(root), mid + 1, right);
a[root].min = min(a[L(root)].min, a[R(root)].min);
a[root].max = max(a[L(root)].max, a[R(root)].max);
}
}
//flag = true: max
//flag = false: min
int query(int root, int left, int right, int s, int e, bool flag) {
if (left >= s && right <= e) {
return flag ? a[root].max : a[root].min;
} else if (left > e || right < s) {
return flag ? 0 : 0x7fffffff;
} else {
int mid = (left + right) >> 1;
int a = query(L(root), left, mid, s, e, flag);
int b = query(R(root), mid + 1, right, s, e, flag);
return flag ? max(a, b) : min(a, b);
}
}
int main() {
while (~scanf(" %d %d", &N, &Q)) {
for (int i = 1; i <= N; ++i) {
scanf(" %d", height + i);
}
build(1, 1, N);
int A, B;
while (Q--) {
scanf(" %d %d", &A, &B);
printf("%d\n", query(1, 1, N, A, B, true) - query(1, 1, N, A, B, false));
}
}
return 0;
}