线段树第一题
输入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; }