树状数组(BIT)

本文深入讲解了树状数组的基本概念及应用,包括lowbit运算的不同形式及其意义,如何利用树状数组进行高效的单点修改与查询操作,并通过具体示例说明了如何确定某节点所包含的子节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • OI Wiki
  • 《算法笔记》

前言

利用大节点来存储小节点的信息。在查询或修改的时候直接利用大节点的信息,节省时间。

事实上,树状数组的代码要比线段树短得多,思维也更清晰,在解决一些单点修改的问题时,树状数组是不二之选

lowbit运算

形式一

l o w b i t ( x ) = 2 m a x { ⁡ i │ x m o d    2 i = 0 } lowbit(x) = 2^{max \{⁡{i│x\mod 2^i=0\} }} lowbit(x)=2max{ixmod2i=0}

能整除x的最大2的幂次

形式二

l o w b i t ( x ) = x & ( − x ) lowbit(x) = x \&(-x) lowbit(x)=x&(x)

补码储存方式: − x -x x相当于把 x x x二进制每一位取反,再+1,等价于把 x x x二进制最右边1的左边的每一位都取反

那么KaTeX parse error: Expected '}', got '&' at position 9: x\text{ &̲ }(-x)就是x二进制最右边的1和右边的0。

image-20210126111309956

树状数组

基本知识

image-20210126112236745

假设我们大小节点之间的关系是求和。对于原数组 a,我们用新的树状数组 t 来辅助。

t i = a i , i = 1 , 3 , 5 , 7 t_i=a_i, i=1,3,5,7 ti=ai,i=1,3,5,7

t 2 = a 1 + a 2 , t 6 = a 5 + a 6 t_2=a_1+a_2, t_6=a_5+a_6 t2=a1+a2,t6=a5+a6

t 4 = a 1 + a 2 + a 3 + a 4 t_4=a_1+a_2+a_3+a_4 t4=a1+a2+a3+a4

t 8 = ∑ i = 1 8 a i t_8=\sum^8_{i=1} a_i t8=i=18ai

如果要查 a 1 → a 5 a_1→a_5 a1a5的和,如果树状数组存储的是和,直接用 t 5 + t 4 t_5+t_4 t5+t4 即可。查 a 1 → a 7 a_1→a_7 a1a7 的和,直接 t 7 + t 6 + t 4 t_7+t_6+t_4 t7+t6+t4 即可

那么我们主要要解决两个问题:

  • 怎么知道某个点由哪几个点组成?
  • 怎么修改和查询?

怎么知道某个点由哪几个点组成

对于编号为 x x x的某点,由 l o w b i t ( x ) lowbit(x) lowbit(x)个点组成

  • t [ 6 ] t[6] t[6]为例, l o w b i t ( 6 )