树状数组BIT

现多用于计算前缀和,区间和,可在O(logN)时间内得到任意前缀和 。并且支持在O(logN)时间内动态单点修改 树状数组BIT ```c C1=A1 C2=A1+A2 C3=A3 C4=A1+A2+A3+A4 C5=A5 C6=A5+A6 C7=A7 C8=A1+A2+A3+A4+A5+A6+A7+A8

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
其中 `C[i] = A[i - 2k+1] + A[i - 2k+2] + ... + A[i];   //k为i的二进制中从最低位到高位连续零的长度`

例如`i = 8(1000)时候,k = 3`,可自行验证。

## 应用
针对一个数组A,有A0到An个元素,经过W次修改,每次修改一个元素的值,如何快速求其中任意区间内的和问题?

### 如何求和?

![求和](img_1.png)

以7为例,sum求和0-7的计算方法,C的下标数值如何确定,即7开始不断的取lowbit(具体实现见代码lbt)

## 实现

go package main

import “fmt”

type Bit struct {

1
BitTree []int

} // 该函数也可写成 x&(-x) //函数意义:求x中从最低位开始剔除一个1的数值,例如6(110),剔除最低位1转为4(100)需要减2(10),即lbt(6)=2 func (b *Bit) lbt(x int) int {

1
return x - (x & (x - 1))

}

func (b *Bit) Update(x int, v int) {

1
2
3
for i := x+1; i < len(b.BitTree); i += b.lbt(i) {
    b.BitTree[i] += v
}

}

func (b *Bit) GetSum(x int) int {

1
2
3
4
5
sum := 0
for i := x+1; i > 0; i -= b.lbt(i) {
    sum += b.BitTree[i]
}
return sum

}

func Init(a []int) Bit {

1
2
3
4
5
b := Bit{BitTree: make([]int, len(a)+1)}
for i := 0; i < len(a); i++ {
    b.Update(i, a[i])
}
return b

}

func main(){

1
2
3
a := []int{1,1,1,1}
b := Init(a)
fmt.Println(b)

} ```

参考