Skip to content
Rain Hu's Workspace
Go back

[Algo] 3-10. Binary Indexed Tree(Fenwick Tree, BIT)

Rain Hu

前言:
若要對一數組做範圍取值,那麼最快的方法是前綴數組(prefix sum),可以做到O(1)O(1)的查詢,但若要做單點更新需要O(n)O(n)的時間來維護。
而數組則是做單點更新只需要O(1)O(1)的時間,而要範圍取值則需要O(n)O(n)的查詢時間。
故若是查詢遠大於更新的情境,則適用前綴數組;若更新遠大於查詢的情境,則適用一般數組。
那假如查詢與更新的次數一樣多呢(動態更新與查詢的情境),這種情況就可以用到此章節要介紹的資料結構,Binary Indexed Tree 了。
此結構可以做到 O(n)O(n) 的初始化,log(n)\log(n) 的更新與 log(n)\log(n) 的查詢。

範圍查詢單點更新數組O(n)O(1)前綴數組O(1)O(n)BITO(logn)O(logn) \begin{array}{|c|c|c|}\hline &\textsf{範圍查詢}&\textsf{單點更新}\\\\\hline \textsf{數組}&O(n)&O(1)\\\\\hline \textsf{前綴數組}&O(1)&O(n)\\\\\hline \textsf{BIT}&O(\log n)&O(\log n)\\\\\hline \end{array}

簡介

模板

class BIT {
private: 
    vector<int> bit;
    int lowbit(int a) {
        return a & (-a);
    }
public:
    BIT (int n) {
        bit.assign(n+1, 0);
    }
    void add(int idx, int diff) {
        idx++;
        int n = bit.size();
        while (idx < n) {
            bit[idx] += diff;
            idx += lowbit(idx);
        }
    }
    int query(int idx) {
        int sum = 0;
        idx++;
        while (idx > 0) {
            sum += bit[idx];
            idx -= lowbit(idx);
        }
        return sum;
    }
}

回目錄 Catalog


Share this post on:

Previous
[ML] 簡單實作測試
Next
[Algo] 3-1. Two Pointer/Sliding Window