# Binary Indexed Tree (BIT)
##### Aji Hsu 2025/04/15
---
## Usage
To efficiently update and query prefix sums dynamically.
### Compare to Traditional Prefix Sum
* Traditional
* update: `TC = O(N)`
* get: `TC = O(1)`
* Binary Indexed Tree
* update: `TC = O(log(N)))`
* get: `TC = O(log(N))`
### Example
Given
`nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };`
`prefixSum = { 1, 3, 6, 10, 15, 21, 28, 36, 45 };`
* Traditional prefix sum
* If we want to add 1 to the `nums[0]`, it costs `TC = O(N)` to update the `prefixSum`.
```java
prefixSum = { 2, 4, 7, 11, 16, 22, 29, 37, 46 };
```
* Binary Indexed Tree
* Update the `prefixSum` with `TC = O(log(N))`
---
## Implement Binary Indexed Tree
### Concept
**Traditional:**
`nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };`
`prefixSum = { 1, 3, 6, 10, 15, 21, 28, 36, 45 };`
**BIT(1-indexed):**
`nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };`
`prefixSum = { 1, 3, 3, 10, 5, 11, 7, 36, 9 };`
where:
* index-1 store `nums[1]`
* index-2 store `nums[1]~nums[2]`
* index-3 store `nums[3]`
* index-4 store `nums[1]~nums[4]`
* index-5 store `nums[5]`
* index-6 store `nums[5]~nums[6]`
* index-7 store `nums[7]`
* index-8 store `nums[1]~nums[8]`
* index-9 store `nums[9]`
We can compute prefix sums by:
* `sum[1] = prefixSum[1]`
* `sum[2] = prefixSum[2]`
* `sum[3] = prefixSum[3] + prefixSum[2]`
* `sum[4] = prefixSum[4]`
* `sum[5] = prefixSum[4] + prefixSum[5]`
* `sum[6] = prefixSum[6] + prefixSum[4]`
* `sum[7] = prefixSum[7] + prefixSum[6] + prefixSum[4]`
* `sum[8] = prefixSum[8]`
* `sum[9] = prefixSum[9] + prefixSum[8]`
We can update prefix sums by:
* `nums[1] += d --> prefixSum[1], prefixSum[2], prefixSum[8] += d`
* `nums[2] += d --> prefixSum[2], prefixSum[4], prefixSum[8] += d`
* `nums[3] += d --> prefixSum[3], prefixSum[4], prefixSum[8] += d`
* `nums[4] += d --> prefixSum[4], prefixSum[8] += d`
* `nums[5] += d --> prefixSum[5], prefixSum[6], prefixSum[8] += d`
* `nums[6] += d --> prefixSum[6], prefixSum[8] += d`
* `nums[7] += d --> prefixSum[7], prefixSum[8] += d`
* `nums[8] += d --> prefixSum[8] += d`
* `nums[9] += d --> prefixSum[9] += d`
==**Thus, what we should do is to find a even way to split sum into segments optimally.**==
### Lowbit
* lowbit: the rightmost 1-bit in binary
```java
lowbit = n & -n;
```
* example
* $(6)_{10} = (0110)_2$ -->lowbit=$(0010)_2 = (2)_{10}$
* $(8)_{10} = (1000)_2$ -->lowbit=$(1000)_2 = (8)_{10}$
**We use lowbit to define the interval that prefixSum[i] represents.**
* example
* lowbit(6)=2 -->`prefixSum[6]` store the number of interval `(6-2, 6]` that is `[5, 6]`
* lowbit(8)=8 -->`prefixSum[6]` store the number of interval `(8-8, 8]` that is `[1, 8]`
**Explanation of the way we get sum**
Given
```markdown
i
j = i - lowbit(i)
k = j - lowbit(j)
l = k - lowbit(k)
.
.
.
```
We can conclude that:
`sum[i] = prefixSum[i] + prefixSum[j] + prefixSum[k] ...`
* example
* `sum[6] = prefixSum[6] + prefixSum[4]` means -->
* `sum[6] = prefixSum[6] + prefixSum[6 - Lowbit(6)]`
**Explanation of the way we update sum**
* example
* `nums[6] += d --> prefixSum[6], prefixSum[8] += d` means -->
* `nums[6] += d --> prefixSum[6], prefixSum[6 + lowbit(6)] += d`
**Reason we choose lowbit to implement**
Given i = $(100101)_{2}$
**Get sum:**
Minus lowbit until `i == 0`
$(100101)_{2} \rightarrow (100100)_{2} \rightarrow (100000)_{2} \rightarrow (000000)_{2}$
We can know the total `TC = O(digit) = O(log(N))`
**Update sum:**
If array size = $(111111)_{2}$
Add lowbit until `i >= n`
$(100101)_{2} \rightarrow (100110)_{2} \rightarrow (101000)_{2} \rightarrow (110000)_{2} \rightarrow (1100000)_{2}$
We can know the total `TC = O(digit) = O(log(N))`
### Implement (Java)
* `query()`: get sum
* `update()`: update
```java=
class BIT {
private int[] arr;
BIT(int n) {
arr = new int[n + 1];
}
public void update(int i, int delta) {
i++;
while (i < arr.length) {
arr[i] += delta;
i += i & -i;
}
}
public int query(int i) {
i++;
int total = 0;
while (i > 0) {
total += arr[i];
i -= i & -i;
}
return total;
}
}
```