POJ 3264
线段树题目
题目链接:http://poj.org/problem?id=3264
题目大意:在一个区间内找到最大值与最小值之间的差值。
#include <iostream>
using namespace std;
struct P{
int mm, nn, left, right;
// mm指该节点的最大值, nn指该节点的最小值, left指该线段树节点的范围最小值, left指该线段树节点的范围最大值
};
int d[50005],n,q,mmm=0,nnn=1000000;
// mmm存储每次访问区间的最大值, nnn存储每次访问区间的最小值
P dat[200005]; //存储线段树
void init(int k, int l, int r) { //建立线段树
if (r - l == 0) {
dat[k].nn = d[l];
dat[k].mm = d[l];
dat[k].left = l;
dat[k].right = l;
}
else {
int ll = k * 2 + 1, rr = k * 2 + 2, mid = (l + r) / 2;
if ((l + r) % 2 == 1) {
mid = (l + r) / 2;
init(ll, l, mid);
init(rr, mid + 1, r);
}
else {
mid = (l + r) / 2;
init(ll, l, mid - 1);
init(rr, mid, r);
}
dat[k].nn = min(dat[ll].nn, dat[rr].nn);
dat[k].mm = max(dat[ll].mm, dat[rr].mm);
dat[k].left = l;
dat[k].right = r;
}
}
void solve(int a, int b, int k) {
if (a >= dat[k].left && b <= dat[k].right) {
if (a == dat[k].left && b == dat[k].right) {
mmm = max(mmm, dat[k].mm);
nnn = min(nnn, dat[k].nn);
return;
}
solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 1);
solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 2);
}
if (b > dat[k].right) {
if (a == dat[k].left) {
mmm = max(mmm, dat[k].mm);
nnn = min(nnn, dat[k].nn);
return;
}
if (a > dat[k].right) {
return;
}
else {
solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 1);
solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 2);
}
}
if (a < dat[k].left) {
if (b == dat[k].right) {
mmm = max(mmm, dat[k].mm);
nnn = min(nnn, dat[k].nn);
return;
}
if (b < dat[k].left) {
return;
}
else {
solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 1);
solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 2);
}
}
}
int main() {
int a,b;
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; ++i) {
scanf("%d", &d[i]);
}
init(0, 1, n);
while(q--) {
mmm=0,nnn=1000000;
scanf("%d %d", &a, &b);
solve(a, b, 0);
printf("%d\n",mmm-nnn);
}
return 0;
}