线段树入门

首先提示:本文是自学线段树之后的感悟总结,文章参考not_only_success的线段树完全版,百度第一项就是。

建议把那个文档打开放边上,然后看这个。涉及到代码的部分本文可能会省略。


说到线段树,首先要明确用 数组模拟树的概念。以一颗二叉树为例,若根为root 为1,为了方便数组计算,那么它的左右儿子可以用2, 3来表示,即 root << 1 和 root << 1 | 1
类似于:


在这个基础上,如果把上面的节点换成区间,两个子节点的区间合并刚好能组成父节点的区间,就可以做到类似于这样的东西:


这就是线段树的基本形态了。对于需要线段树操作的一个区间,每个数值都对应一个父节点,他们的父节点记录着操作要求中的数据。
举个例子,比如说建一颗关于数组A的线段树,数组A的值为: 5, 8 , 4, 13,并且这颗线段树要完成的操作是求最大值
那么构建出来的线段树应该是这个样子的:


总结一下:线段树就是一个区间管理的树,其中一个区间的子区间靠它的二分子节点来管理,一直到区间为一,也就是叶节点的位置。


然后是对not_only_success的线段树的构建的讲解,为了更方便更快的理解?

//首先有一个定义,因为经常出现
//lson是左子树,rson是右子树,看过前面树的数组表示就能看懂的。
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

然后是建树过程
build(int l, int r, int rt) {
	//看那个文档
}
其中 当 l == r 的时候,代表已经到达最底下的叶子节点,也就是该是数据初始值的地方。 not_only_success的板不需要在节点上记录左右区间,因为每个节点的区间其实可以靠 l 和 r 就完全确定了的。

更新和查询可以直接看那个文档,没有什么特别的。

然后后面提一下写了十多道题的时候遇到的一些情况:
1. 线段树可以用来统计剩余数量和位置。单点更新,区间查询。
2. 线段树的 加减乘,在使用lazy标记的时候,加减都是 += 更新完后置为0 乘的话,是*= 更新完后置为1
3. 线段树的开根号操作,对于 int 的数据量,最多开6次,对于 long long 的数据,最多开8次。所以在更新的时候,lazy标记高于标值的就不用继续更新了。
4. 板在线段树区间合并的时候需要考虑一下下,万一出问题了呢?
5. 哇,好像就没有别的大问题了。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值