二维树状数组
思路不难,比一维的只多了层循环,代码也很短。详见NOCOW的讲解
POJ 1656
/* 题意:一块方格板,要求把一个正方形区域涂黑/涂白/统计黑的数目 算法:二维树状数组 注意:update的时候下标从x和y开始不是习惯的1啊!!!编译前就发现主程序中的错误改了,没想到update函数里也写错了,半天看不出来啊!!! 2011-07-18 14:11 */ #include <stdio.h> #define MAXN 200 int flag[MAXN][MAXN]; int c[MAXN][MAXN]; int lowbit(int i) { return i & -i; } void update(int x, int y, int color) { if (color == flag[x][y]) return ; flag[x][y] = color; int i, j; for (i = x; i <= MAXN; i += lowbit(i)) for (j = y; j <= MAXN; j+= lowbit(j)) c[i][j] += color; } int getsum(int x, int y) { int sum = 0, i, j; for (i = x; i > 0; i -= lowbit(i)) for (j = y; j > 0; j -= lowbit(j)) sum += c[i][j]; return sum; } int main() { int t, k, i, j, x, y, l; char s[10]; scanf("%d", &t); memset(c, 0, sizeof(c)); memset(flag, -1, sizeof(flag)); for (k = 1; k <= t; k++) { scanf("%s%d%d%d", &s, &x, &y, &l); if (s[0] =='B') { for (i = x; i <= x+l-1; i++) for (j = y; j <= y+l-1; j++) update(i, j, 1); } else if (s[0] == 'W') { for (i = x; i <= x+l-1; i++) for (j = y; j <= y+l-1; j++) update(i, j ,-1); } else printf("%d\n", getsum(x+l-1, y+l-1) - getsum(x+l-1,y-1) - getsum(x-1, y+l-1) + getsum(x-1, y-1)); } return 0; }
POJ 1195
/* 改点、求一块矩形区域的和,二维树状数组解决。因为当值小于0的时候要变为0,所以保留了原数组并多加了判断 不能再把j打成i了!!! 开始的时候打成和上次做的改区域一样了,WA了好久。 2011年7月20日12:53:26 */ #include <stdio.h> #define MAXN 1200 int c[MAXN][MAXN]; int a[MAXN][MAXN]; int n; int lowbit(int i) { return i & -i; } void add(int x, int y, int num) { int i, j; //printf("%d %d %d %d\n", n, x, y, num); for (i = x; i <= n; i += lowbit(i)) for (j = y; j <= n; j += lowbit(j)) c[i][j] += num; } int ask(int x, int y) { int i, j, ans = 0; for (i = x; i >= 1; i -= lowbit(i)) for (j = y; j >= 1; j -= lowbit(j)) ans += c[i][j]; return ans; } int query(int x1, int y1, int x2, int y2) { return ask(x2, y2) - ask(x1 - 1, y2) - ask(x2, y1 - 1) + ask(x1 - 1, y1 -1); } int main() { int cmd, s, x, y, x1, y1, x2, y2, k; scanf("%d%d", &k, &n); while (scanf("%d", &cmd) && (cmd != 3)) { if (cmd == 1) { scanf("%d%d%d", &x, &y, &k); if (k < 0 && a[x+1][y+1] + k < 0) k = 0 - a[x+1][y+1]; a[x+1][y+1] += k; add(x + 1, y + 1, k); } else if (cmd == 2) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); //printf("output\n"); printf("%d\n", query(x1 + 1, y1 + 1, x2 + 1, y2 + 1)); } } return 0; }