暑期集训学习笔记———对线段树单点修改的看法(我是一只小萌新,啦啦啦啦啦)

其实,单点修改和建树是差不多的,都是用到了递归具有回溯的性质。单点修改,具体而言:先向下找到要修改的叶子节点(不知道有没有不是修改叶子结点的情况),然后用 PushUp函数更新它的父亲结点,爷爷结点(我就想这样叫),曾爷爷结点,。。。。。。一直到开头的根结点。由于二叉树的性质,每层只用更新一个结点就够了。

第一张图是单点修改的

倒数第二行那个“更新相关的值”就是PushUp函数
第二张图是创建树的在这里插入图片描述f在这里插入图片描述有没有感觉他们很像?

持续更新中~~~~~

这个递归的性质,使得创建树的时候(用sum数组存储树),能遍历一遍数组a。所以,单点修改的时候,就是用的这个遍历的性质,将sum数组(结点)与修改的位置x(a的下标)对应起来。

持续更新中~~~~~X2
其实区间(例如 :1——9)的含义就是数组a的下标(下标为:1——9)。根节点1—9 代表这个结点存储的是1——9的相关信息。所以,一个叶子结点就只存储了数组a一个元素的信息。而树的结点又是用sum数组(当题目的要求是求和时)来存储的。所以,当l==r时(比如在build,即建树的函数里),会有sum【rt】=a【l】,因为l和r的含义是区间的端点,而区间里点的含义又是数组a某个点的下标。

还有,关于为什么r与l(区间)经过好多次折半的运算后,肯定会相等。这个应该是一个数学知识,就好像我们原来在高中里接触过的二分逼近,肯定会使两个数(两个区间端点)无线逼近一个实数。但是,我们这里只有正整数(只取正整数),所以运算一定次数之后,肯定会使两个数字(r,l)相等。

持续更新中~~~~3(想到啥说啥)
其实,建树,单点修改(比如给某个数增加一个数),(应该还有别的,只要是用到了递归,可能都属于这种情况)都是用到了回溯的性质来实现树的创建和维护(就是,对树的信息的更新)的。而关于上面提到的那两个,之所以一定要在函数里有形参 l 和 r 的原因,就是要通过形参,来遍历叶子结点。比如,单点修改(从判断条件就能看出来)。

``
//单点修改的代码(以增加一个数为例)
void Add(int pos,int l,int r,int rt,int num) //这些参数分别代表 要修改的点的下标,当前结点左右区
//间,当前树节点的下标,要增加的数字。
{
if(l== r&&pos==l) //到达叶子结点。//这里要格外理解。因为,l 和 r 是区间数字,也代表a数组的下标呀。
{
sum[rt]+=num;
return ;
}

int mid=(l+r)>>1;
if(pos<=mid) Add(pos,l,mid,rt<<1,num);
if(pos>mid) Add(pos,mid+1,r,rt<<1|1,num);
PushUp(rt);

}
/*关于这个功能,在main函数里的写法(个人感觉,看了在main函数里的写法
之后,更容易理解有关线段树的这些函数。)
*/
int main()
{
add(5,1,9,2); //这些参数分别代表 要修改的点的下标,当前结点左右区
//间,当前树节点的下标,要增加的数字。
}



**感谢**,,**XYX**大佬,和各位**学长们**为我们这些老鲜肉提供了大部分理论知识。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值