线段树.2

一.点更新

这很好办,有没有注意我们是使用了一个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; //返回求得的区间和。
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值