0
点赞
收藏
分享

微信扫一扫

算法基础11 —— 树进阶(树状数组与线段树入门)

蚁族的乐土 2022-01-26 阅读 106

前置知识

前缀和与差分

树状数组与线段树的整体关系

  • 线段树更为的宏观(可以理解为线段树的作用效果包含树状数组)
  • 树状数组的代码较短

树状数组的作用

  • 以O(logn)的时间复杂度给某个位置上的数加上一个数(单点修改)
  • 以O(logn)的时间复杂度求前缀和(区间查询)

树状数组可以快速、动态地求前缀和。
例如,有一个数组
在这里插入图片描述
将数组下标为4的位置加1,使其变为
在这里插入图片描述
同时,前四个数字的前缀和也由10变成了11

时间复杂度分析

对于一个长度为N的数组,如果修改了第一个元素的值,那么该点之后的前缀和都会发生变化,不利用树状数组修改,时间复杂度为O(n),大于树状数组的O(logn)

树状数组的构造(证明略)

  • 树状数组的下标从1开始
  • 树状数组是一个一维的数组
  • 设原数组为A,树状数组为C,若下标x为奇数,则C[x] = A[x]
  • 如何确定层数?对于C[x],若x的二进制末尾有k个0,则C[x]在第k层
  • 如何确定范围?C[x]等于左开右闭区间(x - 2^k,x]中所有数的和
  • lowbit(x) = x & -x对于一个数x,如果其二进制的末尾有k个0,则返回2^k
  • 综上,C[x]等于左开右闭区间(x - lowbit(x),x]中所有数的和

不难发现:
C[1] = A[1]
C[2] = A[1] + A[2]
C[3] = A[3]
C[4] = A[1] + A[2] + A[3] + A[4]
C[5] = A[5]
C[6] = A[5] + A[6]
C[7] = A[7]
C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]
C[9] = A[9]
C[10] = A[9] + A[10]
C[11] = A[11]
C[12] = A[9] + A[10] + A[11] + A[12]
C[13] = A[13]
C[14] = A[13] + A[14]
C[15] = A[15]
C[16] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]
+A[9] + A[10] + A[11] + A[12] + A[13] + A[14] + A[15] + A[16]
… …

根据以上信息,可以画出如下的树状数组
在这里插入图片描述

举报

相关推荐

0 条评论