【模板】树状数组
一维树状数组
#define lowbit(x) ((x) & (-x))
const int maxN = 1e6 + 10;
typedef long long ll;
struct BIT {
ll data[maxN << 2];
inline void add(int k, int x) {
while (k <= N) {
data[k] += x;
k += lowbit(k);
}
}
inline ll query(int k) {
ll ans = 0;
while (k >= 1) {
ans += data[k];
k -= lowbit(k);
}
return ans;
}
};
单点修改区间查询
BIT B;
inline void add(int k, int x) {
B.add(k, x);
}
inline ll query(int l, int r) {
return B.query(r) - B.query(l - 1);
}
区间修改区间查询
BIT B1, B2;
inline void add(int l, int r, int x) {
B1.add(l, x);
B1.add(r + 1, -x);
B2.add(l, x * (l - 1));
B2.add(r + 1, -x * r);
}
inline ll query(int l, int r) {
ll s1 = (l - 1) * B1.query(l - 1) - B2.query(l - 1);
ll s2 = r * B1.query(r) - B2.query(r);
return s2 - s1;
}
二维树状数组
#define lowbit(x) ((x)&(-x))
const int maxN = 5e3;
typedef long long ll;
struct BIT2 {
ll data[maxN][maxN];
inline void add(int x, int y, int val) {
for (int i = x; i <= N; i += lowbit(i)) {
for (int j = y; j <= M; j += lowbit(j)) {
data[i][j] += val;
}
}
}
inline ll query(int x, int y) {
ll ans = 0;
for (int i = x; i; i -= lowbit(i)) {
for (int j = y; j; j -= lowbit(j)) {
ans += data[i][j];
}
}
return ans;
}
};
单点修改矩阵查询
BIT2 B;
inline void add(int x, int y, int val) {
B.add(x, y, val);
}
inline ll query(int x1, int y1, int x2, int y2) {
return B.query(x2, y2) - B.query(x1 - 1, y2) - B.query(x2, y1 - 1) + B.query(x1 - 1, y1 - 1)
}
矩阵修改矩阵查询
BIT2 B1, B2, B3, B4;
inline void upd(int x, int y, ll k) {
B1.add(x, y, k);
B2.add(x, y, x * k);
B3.add(x, y, y * k);
B4.add(x, y, x * y * k);
}
inline ll que(int x, int y) {
return B1.query(x, y) * (x + 1) * (y + 1) -
B2.query(x, y) * (y + 1) -
B3.query(x, y) * (x + 1) +
B4.query(x, y);
}
inline void add(int a, int b, int c, int d, ll x) {
upd(a, b, x);
upd(c + 1, d + 1, x);
upd(c + 1, b, -x);
upd(a, d + 1, -x);
}
inline ll query(int a, int b, int c, int d) {
return que(c, d) - que(a - 1, d) - que(c, b - 1) + que(a - 1, b - 1);
}