一.点更新
这很好办,有没有注意我们是使用了一个father数组,如果我在原数组中修改第i个元素的值,我们是直接可以node[father[i]].value=w,这就是我们使用father数组的好处,那你可能会问了,我们这样是不是要使用三个数组?大可不必,我们没必要给原有数据开一个数组存放,因为我们本身就已经把数据放在线段树中了,不管线段树中存放的是区间和还是区间最值,对于叶子结点来说,它就是本身。那么我们加入了点,自然也要更新整棵树,那有关这个叶子结点到根节点的路径自然全部都是要更新的,我们则是从下往上利用递归思想来更新的。
void UpdateTree(int ri){
if(ri==1){
return;
}
int fi=ri>>1;//获得父结点下标。
node[fi].value=node[fi<<1].value+node[fi<<1|1].value;//两段区间总和。
UpdateTree(fi);
}
2、区间查询
基本思想:1、如果这个区间被完全包括在目标区间里面,直接返回这个区间的值
2、如果这个区间的左儿子和目标区间有交集,那么搜索左儿子
3、如果这个区间的右儿子和目标区间有交集,那么搜索右儿子
明白这样就ok了
//区间查询,调用函数时为QueryTree(1,l,r),即从根节点自上往下查询。
int QueryTree(int i,int l,int r){
int sum=0;
if(l==node[i].left&&r==node[i].right){
//如果刚好就是这个区间,我们直接返回。
sum+=node[i].value;
return sum;
}
i=i<<1;
if(l<=node[i].right){
//说明部分包含左子树
if(r<=node[i].right){
//说明全包含在左子树。
sum+=QueryTree(i,l,r);
}
else{
sum+=QueryTree(i,l,node[i].right);
}
}
i+=1;
if(r>=node[i].left){
//说明部分包含右子树
if(l>=node[i].left){
//说明全包含在右子树。
sum+=QueryTree(i,l,r);
}
else{
sum+=QueryTree(i,node[i].left,r);
}
}
return sum; //返回求得的区间和。
}