题目链接在这里
题目描述:
给出n个数q次询问,每次询问求[ x, y ]区间最大的数减去最小的数的结果。
思路分析:
用线段树的每个节点存储子节点的最大数和最小数,叶子节点的最大数和最小数是自己。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#define clr(x) memset(x, 0, sizeof(x))
#define rep(i, n) for(int i = 0; i < n; ++i)
#define rl (rt << 1)
#define rr (rt << 1 | 1)
using namespace std;
const int MaxN = 5e4 + 10;
const int INF = 0x3f3f3f3f;
struct Node{
int l, r, mid;
int Max, Min;
}tree[MaxN << 2];
int n, q;
int Max, Min;
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].mid = (l + r) >> 1;
tree[rt].Max = -1;
tree[rt].Min = INF;
if(l == r){
return;
}
build(l, tree[rt].mid, rl);
build(tree[rt].mid + 1, r, rr);
}
void update(int rt, int pos, int w){
if(tree[rt].l == tree[rt].r && tree[rt].l == pos){
tree[rt].Max = tree[rt].Min = w;
return;
}
if(pos <= tree[rt].mid){
update(rl, pos, w);
tree[rt].Max = max(tree[rl].Max, tree[rt].Max);
tree[rt].Min = min(tree[rt].Min, tree[rl].Min);
}
if(pos > tree[rt].mid){
update(rr, pos, w);
tree[rt].Max = max(tree[rt].Max, tree[rr].Max);
tree[rt].Min = min(tree[rt].Min, tree[rr].Min);
}
}
void query(int l, int r, int rt){
if(l == tree[rt].l && tree[rt].r == r){
Max = max(tree[rt].Max, Max);
Min = min(tree[rt].Min, Min);
return;
}
if(tree[rt].mid >= r) query(l, r, rl);
else if(tree[rt].mid < l) query(l, r, rr);
else{
query(l, tree[rt].mid, rl);
query(tree[rt].mid + 1, r, rr);
}
}
int main(){
while(~scanf("%d %d", &n, &q)){
int a, b;
build(1, n, 1);
rep(i, n){
scanf("%d", &a);
update(1, i + 1, a);
}
rep(i, q){
scanf("%d %d", &a, &b);
Min = INF;
Max = -1;
query(a, b, 1);
printf("%d\n", Max - Min);
}
}
return 0;
}