线段树详解

引入例题:(P3372 【模板】线段树 1)已知一个数列,你需要进行下面两种操作:1.将某区间每一个数加上 kkk。2.求出某区间每一个数的和。我们可以使用树状数组来解决这道题,然而这次我们要回归正解了!我们要使用线段树!线段树线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界
摘要由CSDN通过智能技术生成

引入

例题:(洛谷 P3372 【模板】线段树 1

已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上 k k k
2.求出某区间每一个数的和。

我们可以使用树状数组来解决这道题,然而这次我们要回归正解了!我们要使用线段树

线段树

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。——百度百科

实 际 应 用 时 一 般 还 要 开 4 N 的 数 组 以 免 越 界 ! 实际应用时一般还要开 4N 的数组以免越界! 4N!

4 N 的 数 组 ! 4N 的数组! 4N!

4 N 的 数 组 ! 4N 的数组! 4N!

(血淋淋的教训)

线段树能够支持满足结合律的运算的区间操作,查改的时间复杂度均为 O ( l o g n ) O(logn) O(logn),与树状数组相比,它的功能更强大,但是具有常数大,码量大的缺点。对于此,你需要记住以下三点:

  1. 树状数组能解决的问题,线段树一定能解决;
    线段树能解决的问题,树状数组不一定能解决。
  2. 在能用树状数组解决的情况下,尽量用树状数组解决;
    在对常数要求高的情况下,尽量用树状数组解决。
  3. 线段树的代码较为复杂,写挂了的话建议重写。

好,那我们进入正题。

在解决上述区间查改的问题之前,我们先来看一下这个问题

对于这道树状数组的模板题,我们可以使用较为简单的线段树来实现。

我们来看一下线段树的结构图:
请添加图片描述

我们将其填入数字:
请添加图片描述

其中每一个长条就是所谓的“线段”,可以发现,父节点(父线段)被平均分成两个子节点(子线段)。

线段树的原理是什么呢?我们来看上面的图,在实际操作中,上图的线段实际上是不存在的,那么存在的是什么呢?是线段内各数的和。

这样,我们可以发现,每个节点的值都等于其两个儿子的和,叶子节点的值为原数。

请添加图片描述
我们来模拟一下单点修改的过程:

我们要将第 3 3 3 个数加上 2 2 2,也就是将 4 4 4 2 2 2

首先,修改叶子节点:

请添加图片描述
依次向上累加,注意,在实际操作中只是将父节点更新为子节点之和(push_up),而并不需要更新线段上的数值,这里是为了便于理解。

最后更新完是这样的:
请添加图片描述
那查询呢?

假设我们要求 [ 2 , 4 ] [2,4] [2,4] 的和,这时我们要做相反的操作,即从根开始。

首先,在根节点找到需操作的区间:

请添加图片描述
向下分割:

请添加图片描述
继续分割,直到分割到完整的线段,返回线段的值:

请添加图片描述
请添加图片描述

至此,我们已经解决了单点修改和区间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值