当前位置: 首页 > ds >正文

树状数组详解

树状数组

概念:

树状数据结构,通常维护一些带有差分性质的区间问题,比如单点加,单点乘,查询区间和,前后缀最大值、最小值等。

回顾线段树:

线段树得以快速修改和查询在于下传懒标记,而树状数组则是每次修改时,将标记上传,查询的时候不用像线段树一样每次 pushdown。区别之处在于标记传送的方式的不同。

树状数组的图示:

和线段树不同,我们定义一个点,其儿子的范围(就是存的哪一个区间的范围)是 [ i − 2 k + 1 , i ] [i-2^k+1,i] [i2k+1,i] 其中 k k k i i i 二进制下从后往前第一个为 1 1 1 的位置,下标从0开始计算,我们称这个值为 l o w b i t i lowbit_i lowbiti

比如: l o w b i t 3 = l o w b i t ( 11 ) 2 = 2 0 = 1 lowbit_3=lowbit_{(11)_2}=2^0=1 lowbit3=lowbit(11)2=20=1

先解决如何快速计算 l o w b i t lowbit lowbit 首先暴力枚举一个二进制位数,然后判断这一位在原数的二进制下是否是1,这样是 log ⁡ n \log n logn 的,有点慢了。

考虑二进制的一些性质,因为二进制数也有着进位退位这个说法,假设一个数 x x x 它二进制下从后往前第一个 1 出现的位置为 k k k 那么如果将 x → x − 1 x→x-1 xx1 转换成二进制,就会变成 k k k 之前的还是那样, k k k 这个位置为 0 , k k k 之后的位置都是 0。

比如 ( 10100 ) 2 − 1 10 → ( 10011 ) 2 (10100)_{2}-1_{10}→(10011)_2 (10100)2110(10011)2

这个时候我们再跟原数 x x x 进行异或操作,就变成了 10100 x o r 10010 10100 xor 10010 10100xor10010 就变成了 00111 00111 00111 然后再跟原数 x x x 取 & 操作,也就是把 k k k 之后那些没用的 0 给挤掉。

int lowbit(int x){return x&(x^(x-1));
}

这样有点复杂啊,怎么让他好看点呢?

由于补码是反码+1,也就是 10100 10100 10100

反码: 01011 01011 01011

补码: 01100 01100 01100

好玩的事情出现了,我们发现补码的+1会一直进位,什么时候不进位呢,显然就是进位到一个位置 k k k 这个地方为0,就会停止进位,而这个0正是原数反码中的从后往前的第一个出现的1的位置,这样把两个数 & 起来结果就对了。

那么知道了这些,树状数组有哪些性质呢?

  • 对于节点 i i i 其直接父亲编号为 i + l o w b i t i i+lowbit_i i+lowbiti

那么修改的时候我们就可以把所有的 x > i x>i x>i 满足 x x x 中有 i i i 的信息都给打上标记。

单点修改打标记的时间复杂度:

由于我们发现 x → x + l o w b i t x x→x+lowbit_x xx+lowbitx 的操作实际上是进位操作,所以最多会进行 log ⁡ 2 V \log_2 V log2V 次操作, V V V 是树状数组节点个数,也就是树状数组值域。

这样修改操作就可以了,我们看查询操作:

前文已经提及了,树状数组需要满足差分性质,比如求区间和就有差分性质,求区间 ∑ i = l r a i \sum_{i=l}^r a_i i=lrai 的值,就可以求 ∑ i = 1 r a i − ∑ i = 1 l − 1 a i \sum_{i=1}^ra_i-\sum_{i=1}^{l-1}a_i i=1raii=1l1ai

http://www.xdnf.cn/news/2413.html

相关文章:

  • ZBrush2025建模软件下载 ZBrush中文版免费下载 ZBrush版本大全
  • 数据预处理中比较重要的知识点
  • 【白雪讲堂】
  • CPU与GPU的功能与区别解析
  • 【LCMM】纵向轨迹模型,组轨迹模型
  • c++学习小结
  • AUTOSAR图解==>AUTOSAR_SWS_StandardTypes
  • PotPlayer,强大的高清视频播放器
  • 使用 Spring Boot 进行开发
  • TypeScript基础数据类型详解
  • 多数元素(简单)
  • VSCode远程登录云服务器并设置免密登录全攻略
  • java每日精进 4.26【多租户之过滤器及请求处理流程】
  • llama factory怎么命令行推理图片
  • java—基础
  • A. Everybody Likes Good Arrays!
  • Java 程序运行和类路径处理
  • map和set的应用总结
  • MySQL 常用语句教程
  • Python数值类型修炼手册:从青铜到王者的进阶之路
  • Buffer Pool是什么,有什么作用
  • 【MATLAB第118期】基于MATLAB的双通道CNN多输入单输出分类预测方法
  • Android学习总结之协程对比优缺点(协程一)
  • 腾讯云智三道算法题
  • 侵水防触电的原理是什么? 侵水防触电算先进技术吗?-优雅草卓伊凡
  • 【Redis——通用命令】
  • 写时拷贝讲解
  • SQL:MySQL 函数
  • Eigen库入门
  • 博客文章格式更新2.0