---
title: Fenwick (BIT, 樹狀數組)
tags: 基礎資料結構
---
:::info
題目放這裡~
- [TIOJ 1080](https://tioj.ck.tp.edu.tw/problems/1080)
- [ZJ d799](https://zerojudge.tw/ShowProblem?problemid=d799)
- [ATC DPcontest PQ](https://atcoder.jp/contests/dp/tasks/dp_q)
- [TIOJ 1869](https://tioj.ck.tp.edu.tw/problems/1869)
- [Codechef SUBARR](https://www.codechef.com/problems/SUBARR)
:::
:::success
## 樹狀數組
- 支援:單點加值,前綴和(時間複雜度 $O(logn)$ )
- 空間複雜度:$O(n)$
```cpp=
const int MAXN;
int BIT[MAXN+5];
//單點加值
void add(int k, int val){
while(k <= MAXN){
BIT[k] += val;
k += (k&-k);
}
}
//前綴和
int sum(int k){
int ret = 0;
while(k){
ret += BIT[k];
k -= (k&-k);
}
return ret;
}
```
:::
:::success
## 離散化
- 當只在乎序列中的大小關係的時候,可以使用離散化,縮小數值範圍
- 其實就是排序+編碼
:::
:::success
## 講講 ZJ d799
- [ZJ d799](https://zerojudge.tw/ShowProblem?problemid=d799)
原本數列:$a_1, a_2, a_3, ..., a_n$
=> $a_1-0, a_2-a_1, a_3-a_2, a_4-a_3, ...$
差分數列:$d_1, d_2, d_3, d_4...$
- 區間修改,單點求值:
- 對差分數列建 BIT
- 修改:$[a_3, a_7]$ 都加上 $k$
- $d_3 = a_3-a_2 += k$
- $d_8 = a_8-a_7 -= k$
- 求值:$a_i = \sum_{1}^{j}{d_j}$
- 區間修改,區間和:
- 區間和:$[a_3, a_7]$ 的區間和
- $\sum_{3}^{7}a_i = \sum_{3}^{7}\sum_{1}^{j}{d_j}$
- $=d_1*5+d_2*5+d_3*5+d_4*4+d_5*3+d_6*2+d_7*1$
- $=(d_1+d_2+d_3+d_4+d_5+d_6+d_7)*5-(d_4*1+d_5*2+d_6*3+d_7*4)$
- $a_3 = (d_1+d_2+d_3)$
- $a_4 = (d_1+d_2+d_3+d_4)$
- $a_5 = (d_1+d_2+d_3+d_4+d_5)$
- $a_6 = (d_1+d_2+d_3+d_4+d_5+d_6)$
- $a_7 = (d_1+d_2+d_3+d_4+d_5+d_6+d_7)$
- 再建一個BIT:
- $d_1*1, d_2*2, d_3*3, ...$
- 區間和:
- $=(d_1+d_2+d_3)*5+(d_4+d_5+d_6+d_7)*8-(d_4*4+d_5*5+d_6*6+d_7*7)$
:::