树状数组或二叉索引树(英语:Binary Indexed Tree),又以其发明者命名为Fenwick树,最早由Peter M. Fenwick于1994年以A New Data Structure for Cumulative Frequency Tables为题发表在SOFTWARE PRACTICE AND EXPERIENCE。其初衷是解决数据压缩里的累积频率(Cumulative Frequency)的计算问题,现多用于高效计算数列的前缀和, 区间和。它可以以的时间得到任意前缀和!,并同时支持在时间内支持动态单点值的修改。空间复杂度。
按照Peter M. Fenwick的说法,正如所有的整数都可以表示成2的幂和,我们也可以把一串序列表示成一系列子序列的和。采用这个想法,我们可将一个前缀和划分成多个子序列的和,而划分的方法与数的2的幂和具有极其相似的方式。一方面,子序列的个数是其二进制表示中1的个数,另一方面,子序列代表的f[i]的个数也是2的幂。
int n, a[MAXN], bit[MAXN]; // n 为元素个数,a 为原数组,bit 为差分数组
voidModify(int pos, int x){ for (; pos <= n; pos += lowbit(pos)) bit[pos] += x; }
voidrangeModify(int l, int r, int x){ Modify(l, x); Modify(r + 1, -x); }
intQuery(int pos){ int ret = 0; for (; pos >= 1; pos -= lowbit(pos)) ret += bit[pos]; return ret; }
intmain(){ ... for (i = 1 to n increase 1) { read a[i] rangeModify(i, i, a[i]); } ... read x, read y, read k rangeModify(x, y, k); // 将 [x,y] 区间内的数加上 k ... read k printf("%d\n", Query(k)); // 查询 k 位置的元素 }
// 是不是和一维的手法差不多(逃 voidModify(int x, int y, int w){ for (; x <= n; x += lowbit(x)) { for (int fy = y; fy <= m; fy += lowbit(fy)) { // 说一个坑:这里不要对 y 进行直接修改 // 因为下一次循环 x 的时候需要用 y // 我当初在这里栽坑调了快 10min。。。 bit[x][fy] += w; } } } intQuery(int x, int y){ int ans = 0; for (; x >= 1; x -= lowbit(x)) { for (int fy = y; fy >= 1; fy -= lowbit((fy))) { ans += bit[x][fy]; } } return ans; } intmatrixQuery(int x1, int y1, int x2, int y2){ // x1 <= x2, y1 <= y2 int a = Query(x2, y2); int b = Query(x1 - 1, y2); int c = Query(x2, y1 - 1); int d = Query(x1 - 1, y1 - 1); return a - b - c + d; }
下标从 1 开始 12345 100000 200000 300000 400000 修改(1,2)->(4,3) + x 12345 100000 2 x 000 -x 300000 4 -x 000 x 前缀和: 12345 100000 2 x x x x 0 3 x x x x 0 400000
#define FILE_IN(__fname) freopen(__fname, "r", stdin) #define FILE_OUT(__fname) freopen(__fname, "w", stdout) #define rap(a,s,t,i) for (int a = s; a <= t; a += i) #define basketball(a,t,s,i) for (int a = t; a > s; a -= i) #define countdown(s) while (s --> 0) #define IMPROVE_IO() std::ios::sync_with_stdio(false) #define lowbit(x) ((x & (-x)))
namespace BIT { int d[MAXN][MAXN], di[MAXN][MAXN]; int dj[MAXN][MAXN], dij[MAXN][MAXN];
voidModify(int x, int y, int w){ for (int i = x; i <= n; i += lowbit(i)) { for (int j = y; j <= m; j += lowbit(j)) { d[i][j] += w; di[i][j] += w * x; dj[i][j] += w * y; dij[i][j] += w * x * y; } } } voidmatrixModify(int x1, int y1, int x2, int y2, int w){ Modify(x1, y1, w); Modify(x2 + 1, y2 + 1, w); Modify(x1, y2 + 1, -w); Modify(x2 + 1, y1, -w); } intQuery(int x, int y){ int ret = 0; for (int i = x; i >= 1; i -= lowbit(i)) { for (int j = y; j >= 1; j -= lowbit(j)) { ret += d[i][j] * (x + 1) * (y + 1) - (y + 1) * di[i][j] - (x + 1) * dj[i][j] + dij[i][j]; } } return ret; } intmatrixQuery(int x1, int y1, int x2, int y2){ int a = Query(x2, y2); int b = Query(x1 - 1, y1 - 1); int c = Query(x1 - 1, y2); int d = Query(x2, y1 - 1); return a - c - d + b; } }
intmain(){ std::ios::sync_with_stdio(false); std::string _s; cin >> _s; cin >> n >> m; // rap (i, 1, n, 1) { // rap (j, 1, m, 1) { // int fx = 0; // scanf("%d", &fx); // BIT::matrixModify(i, j, i, j, fx); // } // } char ch = 0; while (cin >> ch) { int a = 0, b = 0, c = 0, d = 0; cin >> a >> b >> c >> d; if (ch == 'L') { int delta = 0; cin >> delta; BIT::matrixModify(a, b, c, d, delta); } else { // scanf("\n"); // printf("%d\n", BIT::matrixQuery(a, b, c, d)); cout << BIT::matrixQuery(a, b, c, d) << endl; } // getchar(); } return0; }