Contents
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define Lson(x) (x<<1) //左移相当于乘2; 2*n
#define Rson(x) (Lson(x)|1) //相当于2*n + 1
#define Mid(x,y) ((x+y)>>1) //右移相当于除2,相当于n / 2
#define Sum(x,y) (x+y)

const int N = 10;
const int MAXN = 50010;

int n, m;
int num[MAXN];
struct Node{
int left;
int right;
int sum;
int sum2;
};
Node node[MAXN << 2]; //n个数,则线段树占4倍n的内存

void push_up(int pos){
node[pos].sum = max(node[Lson(pos)].sum,node[Rson(pos)].sum);
node[pos].sum2 = min(node[Lson(pos)].sum2,node[Rson(pos)].sum2);
}

void init(int left , int right , int pos){
node[pos].left = left;
node[pos].right = right;

if(left == right){ //叶子节点
node[pos].sum = num[left];
node[pos].sum2 = num[left];
return;
}

int x = Mid(left , right);

init(left , x , Lson(pos)); //向左节点去
init(x+1 , right , Rson(pos)); //向右节点去
push_up(pos); //回溯的时候对本节点的sum赋值(左孩子的sum+右孩子的sum)
}

int queryMax(int left , int right , int pos){
if(node[pos].left == left && node[pos].right == right)
return node[pos].sum;

int x = Mid(node[pos].left , node[pos].right);

if(right <= x) //在左孩子的区间里
return queryMax(left , right , Lson(pos));
else if(left > x) //在右孩子的区间里
return queryMax(left , right , Rson(pos));
else //如果有部分在左孩子的区间和右孩子的区间里,就将其分为两个区间
return max(queryMax(left , x , Lson(pos)), queryMax(x+1 , right , Rson(pos)));
}

int queryMin(int left , int right , int pos){
if(node[pos].left == left && node[pos].right == right)
return node[pos].sum2;

int x = Mid(node[pos].left , node[pos].right);

if(right <= x) //在左孩子的区间里
return queryMin(left , right , Lson(pos));
else if(left > x) //在右孩子的区间里
return queryMin(left , right , Rson(pos));
else //如果有部分在左孩子的区间和右孩子的区间里,就将其分为两个区间
return min(queryMin(left , x , Lson(pos)), queryMin(x+1 , right , Rson(pos)));
}

int main(){
int q;
while(scanf("%d%d", &n, &q) != EOF)
{
for(int i = 1; i <= n; i++)
scanf("%d", &num[i]);
init(1, n, 1);
int left, right;
for(int i = 0; i < q; i++){
scanf("%d%d", &left, &right);
printf("%d\n", queryMax(left, right, 1) - queryMin(left, right, 1));
}
}
return 0;
}
Contents