给定Q (1 ≤ Q ≤ 200,000)个数A1,A2 … AQ,,多次求任一区间Ai – Aj中最大数和最小数的差。
Sample Input
6 3 //6个数,3次个查询
1
7
3
4
2
5
1 5
4 6
2 2
Sample Output
6
3
0
感悟:
遵循三个过程:
- 建树过程
- 存输过程
- 查询过程
每一个都要用到比较和递归。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct Node{
int L,R;
int min,max;
int mid(){
return (L+R)/2;
}
}tree[800010];
int minV=(1<<30);
int maxV=-(1<<30);
void BuiltTree(int root,int L,int R){
tree[root].L=L;
tree[root].R=R;
tree[root].min=(1<<30);
tree[root].max=-(1<<30);
if(L!=R){
BuiltTree(2*root+1,L,(L+R)/2);
BuiltTree(2*root+2,(L+R)/2+1,R);
}
}
void Insert(int root,int i,int t){
if(tree[root].L==tree[root].R){
tree[root].min=tree[root].max=t;
return;
}
tree[root].max=max(tree[root].max,t);
tree[root].min=min(tree[root].min,t);
if(i<=tree[root].mid()){
Insert(2*root+1,i,t);
}else{
Insert(2*root+2,i,t);
}
}
void Query(int root,int s,int e){
if(tree[root].min>=minV&&tree[root].max<=maxV){
return;
}
if(tree[root].L==s&&tree[root].R==e){
minV=min(minV,tree[root].min);
maxV=max(maxV,tree[root].max);
return;
}
if(e<=tree[root].mid()){
Query(2*root+1,s,e);
}else if(s>tree[root].mid()){//
Query(2*root+2,s,e);
}else{
Query(2*root+1,s,tree[root].mid());
Query(2*root+2,tree[root].mid()+1,e);
}
}
int main(){
int n,q;
scanf("%d %d",&n,&q);
BuiltTree(0,1,n);
for(int i=1;i<=n;i++){
int t;
scanf("%d",&t);
Insert(0,i,t);
}
for(int j=1;j<=q;j++){
int s,e;
scanf("%d %d",&s,&e);
minV=(1<<30);
maxV=-(1<<30);
Query(0,s,e);
printf("%d\n",maxV-minV);
}
return 0;
}
注意:不能用c++的输入输出函数,铁定超时