问题:从1~100的区间中,你想算出其中3 ~ 27中区间的值;
一般你会怎么做?for(int i=3;i<=27;i++)sum+=num[i];但这样速度太慢了。
现在我们求四个区间1,2,3,4 我们求其中1~3的和。
先建立一棵线段树
线段树建树
然后我们要求13的和,我们先从根节点开始查询,发现她的左儿子12这个区间和答案区间1~3有交集,那么我们跑到左儿子这个区间。
然后,我们发现这个区间12被完全包括在答案区间13这个区间里面,那就把她的值3返回。
我们回到了14区间,发现她的右儿子34区间和答案区间13有交集,那么我们走到34区间
到了34区间,我们发现她并没有完全包含在答案区间13里面,但发现她的左儿子33区间和13区间又交集,那么久走到3~3区间
到了3~3区间,发现其被答案区间完全包含,就返回她的值3一直到最开始
33区间的3+12区间的3=6,我们知道了1~3区间和为6.
我们总结一下,线段树的查询方法:
1、如果这个区间被完全包括在目标区间里面,直接返回这个区间的值
2、如果这个区间的左儿子和目标区间有交集,那么搜索左儿子
3、如果这个区间的右儿子和目标区间有交集,那么搜索右儿子
写成代码,就会变成这样:
inline int search(int i,int l,int r){
if(tree[i].l>=l && tree[i].r<=r)//如果这个区间被完全包括在目标区间里面,直接返回这个区间的值
return tree[i].sum;
if(tree[i].r<l || tree[i].l>r) return 0;//如果这个区间和目标区间毫不相干,返回0
int s=0;
if(tree[i*2].r>=l) s+=search(i*2,l,r);//如果这个区间的左儿子和目标区间又交集,那么搜索左儿子
if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r);//如果这个区间的右儿子和目标区间又交集,那么搜索右儿子
return s;
}