线段树第一题
输入n和m共有n个数,m个操作
在m个操作中输入a和b在a和b的范围中求出最大值减最小值的和
线段树区间更新问题,将num数组的数先放入到线段树里面的叶子节点,也就是说最底下一层从左到右按顺序就是num[i]的值
在build方法过程中从叶子节点开始向上更新,每两个节点取一个最大和最小
层层更新上去到了树根的时候就是第1个到第n个数的最大值和最小值
如果要具体查询a到b,其实就是查询线段为a到b的最大值减最小值
代码中根据习惯用到了位运算
i<<1就是2*i也就是左孩子序号
i<<1就是2*i+1也就是右孩子序号
i>>1就是i/2其中
mid就是l和r的中点
上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 50005
using namespace std;
struct node {
int l, r, maxn, minn;
}tree[N<<2];
int max1,min1;
int num[N];
void build(int l,int r,int i)
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].maxn=tree[i].minn=num[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
tree[i].maxn=max(tree[i<<1].maxn,tree[i<<1|1].maxn);
tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);
}
void query(int l,int r,int i)
{
if(l<=tree[i].l&&r>=tree[i].r)
{
min1=min(tree[i].minn,min1);
max1=max(tree[i].maxn,max1);
return ;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(mid<l)query(l,r,i<<1|1);
else if(mid>=r)query(l,r,i<<1);
else {
query(l,r,i<<1);
query(l,r,i<<1|1);
}
}
int main()
{
int n,m;
int a,b;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,n,1);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
min1=99999999;
max1=-99999999;
query(a,b,1);
printf("%d\n",max1-min1);
}
return 0;
}