模板

单点修改的树状数组

template<typename T>
struct fenwick_tree {

    std::vector<T> ft;
    size_t size;

    fenwick_tree() = default;
    fenwick_tree(size_t n) 
        : ft(n + 1, 0), size(n) {}

    void modify(int pos, T value) {
        for (; pos <= size; pos += (pos & (-pos))) {
            ft[pos] += value;
        }
    }

    T query(int pos) {
        T res = 0;
        for (; pos >= 1; pos -= (pos & (-pos))) {
            res += ft[pos];
        }
        return res;
    }

    T query(int left, int right) {
        return query(right) - query(left - 1);
    }
};

初始化

fenwick_tree<int> ft(n) 构造类型为 int ,范围为 \([0, n]\) 的树状数组。

单点修改

modify(pos, value)pos 修改的点的下标, value 修改的 + 值。

查询

query(left, right), 查询范围\([left, right]\), 单点也是范围。

区间修改的树状数组

template<typename T>
struct fenwick_tree {

    std::vector<T> ft1, ft2;
    size_t size;

    fenwick_tree() = default;
    fenwick_tree(size_t n) 
        : ft1(n + 1, 0), ft2(n + 1, 0), size(n) {}

    void modify(int pos, T value) {
        for (T value2 = value * pos; pos <= size; pos += (pos & (-pos))) {
            ft1[pos] += value;
            ft2[pos] += value2;
        }
    }

    T query(std::vector<T>& ft, int pos) {
        T res = 0;
        for (; pos >= 1; pos -= (pos & (-pos))) {
            res += ft[pos];
        }
        return res;
    }

    void modify(int left, int right, T value) {
        modify(left, value);
        modify(right + 1, -value);
    }

    T query(int left, int right) {
        return ((1LL + right) * query(ft1, right) - (1LL * left * query(ft1, left - 1)))
         - (query(ft2, right) - query(ft2, left - 1));
    }
};

初始化

fenwick_tree<int> ft(n) 构造类型为 int ,范围为 \([0, n]\) 的树状数组。

修改

modify(left, right, value), 修改范围为 \([left, right]\)value 修改的 + 值。

查询

query(left, right), 查询范围\([left, right]\), 单点也是范围。

单点修改的二维树状数组

template<typename T>
struct fenwick2_tree {

    struct vector2 {
        std::vector<T> arr;
        size_t row, col, size;

        vector2() = default;
        vector2(size_t n, size_t m)
            : arr((n + 1) * (m + 1) + 1, 0), row(n), col(m), size(n * m) {}; 

        T& at(int n, int m) {
            if (row < n || col < m) return arr[0]; 
            return arr[n * (col + 1) + m];
        }
    } ft;
    size_t row, col, size;

    fenwick2_tree() = default;
    fenwick2_tree(size_t n, size_t m) 
        : ft(n, m), row(n), col(m), size(n * m) {}

    void modify(int r, int c, T value) {
        for (int i = r; i <= row; i += (i & (-i))) {
            for (int j = c; j <= col; j += (j & (-j))) {
                ft.at(i, j) += value;
            }
        }
    }

    T query(int r, int c) {
        T res = 0;
        for (int i = r; i >= 1; i -= (i & (-i))) {
            for (int j = c; j >= 1; j -= (j & (-j))) {
                res += ft.at(i, j);
            }
        }
        return res;
    }

    T query(int r1, int c1, int r2, int c2) {
        return query(r2, c2) - 
        query(r2, c1 - 1) - 
        query(r1 - 1, c2) + 
        query(r1 - 1, c1 - 1);
    }

};

初始化

fenwick2_tree<int> ft(n, m) 构造类型为 int ,范围为 \(n \times m\) 的树状数组。

单点修改

modify(r, c, value), 修改下标 \((r, c)\) 的值, value 修改的 + 值。

查询

query(r1, c1, r2, c2), 查询左上角坐标为 \((r1, c1)\), 右下角坐标为 \((r2, c2)\) 的矩阵的和, 单点也是矩阵。

区间修改, 单点查询的二维树状数组

template<typename T>
struct fenwick2_tree {

    struct vector2 {
        std::vector<T> arr;
        size_t row, col, size;

        vector2() = default;
        vector2(size_t n, size_t m)
            : arr((n + 1) * (m + 1) + 1, 0), row(n), col(m), size(n * m) {};

        T &at(int n, int m) {
            if (row < n || col < m)
                return arr[0];

            return arr[n * (col + 1) + m];
        }
    } ft;
    size_t row, col, size;

    fenwick2_tree() = default;
    fenwick2_tree(size_t n, size_t m)
        : ft(n, m), row(n), col(m), size(n * m) {}

    void modify(int r, int c, T value) {
        for (int i = r; i <= row; i += (i & (-i))) {
            for (int j = c; j <= col; j += (j & (-j))) {
                ft.at(i, j) += value;
            }
        }
    }

    T query(int r, int c) {
        T res = 0;
        for (int i = r; i >= 1; i -= (i & (-i))) {
            for (int j = c; j >= 1; j -= (j & (-j))) {
                res += ft.at(i, j);
            }
        }
        return res;
    }

    void modify(int r1, int c1, int r2, int c2, T value) {
        modify(r1, c1, value);
        modify(r1, c2 + 1, -value);
        modify(r2 + 1, c1, -value);
        modify(r2 + 1, c2 + 1, value);
    }
};

初始化

fenwick2_tree<int> ft(n, m) 构造类型为 int ,范围为 \(n \times m\) 的树状数组。

修改

modify(r1, c1, r2, c2, value), 修改左上角坐标为 \((r1, c1)\), 右下角坐标为 \((r2, c2)\) 的矩阵中每个位置的值, value 修改的 + 值。

查询

query(r, c), 查询单点 \((r, c)\) 的值。

区间修改, 区间查询的二维树状数组

template<typename T>
struct fenwick2_tree {

    struct vector2 {
        std::vector<T> arr;
        size_t row, col, size;

        vector2() = default;
        vector2(size_t n, size_t m)
            : arr((n + 1) * (m + 1) + 1, 0), row(n), col(m), size(n * m) {}; 

        T& at(int n, int m) {
            if (row < n || col < m) return arr[0]; 
            return arr[n * (col + 1) + m];
        }
    } ft1, ft2, ft3, ft4;
    size_t row, col, size;

    fenwick2_tree() = default;
    fenwick2_tree(size_t n, size_t m) 
        : ft1(n, m), ft2(n, m), ft3(n, m), ft4(n, m),
         row(n), col(m), size(n * m) {}

    void modify(int r, int c, T value) {
        for (int i = r; i <= row; i += (i & (-i))) {
            for (int j = c; j <= col; j += (j & (-j))) {
                ft1.at(i, j) += value;
                ft2.at(i, j) += 1LL * (r - 1) * value;
                ft3.at(i, j) += 1LL * (c - 1) * value;
                ft4.at(i, j) += 1LL * (r - 1) * (c - 1) * value;
            }
        }
    }

    T query(int r, int c) {
        T res = 0;
        for (int i = r; i >= 1; i -= (i & (-i))) {
            for (int j = c; j >= 1; j -= (j & (-j))) {
                res += 1LL * r * c * ft1.at(i, j) - 
                        c * ft2.at(i, j) -
                        r * ft3.at(i, j) +
                        ft4.at(i, j);
            }
        }
        return res;
    }

    void modify(int r1, int c1, int r2, int c2, T value) {
        modify(r1, c1, value);
        modify(r1, c2 + 1, -value);
        modify(r2 + 1, c1, -value);
        modify(r2 + 1, c2 + 1, value);
    }

    T query(int r1, int c1, int r2, int c2) {
        return query(r2, c2) - 
        query(r2, c1 - 1) - 
        query(r1 - 1, c2) + 
        query(r1 - 1, c1 - 1);
    }

};

初始化

fenwick2_tree<int> ft(n, m) 构造类型为 int ,范围为 \(n \times m\) 的树状数组。

修改

modify(r1, c1, r2, c2, value), 修改左上角坐标为 \((r1, c1)\), 右下角坐标为 \((r2, c2)\) 的矩阵中每个位置的值, value 修改的 + 值。

查询

query(r1, c1, r2, c2), 查询左上角坐标为 \((r1, c1)\), 右下角坐标为 \((r2, c2)\) 的矩阵的和, 单点也是矩阵。

其他

#130. 树状数组 1 :单点修改,区间查询

#131. 树状数组 2 :区间修改,单点查询

#132. 树状数组 3 :区间修改,区间查询

#133. 二维树状数组 1:单点修改,区间查询

#134. 二维树状数组 2:区间修改,单点查询

#135. 二维树状数组 3:区间修改,区间查询

OI-wiki