题意:
一个二维矩阵,有如下操作:
0 S:创建一个S * S的二维矩阵
1 x y v:在点 [ x , y ] 的值加上 v
2 x1 y1 x2 y2:计算在区间 [ x1 , y1] ~ [ x2 , y2 ] 中所有点的和
3:结束
题意:
一个二维矩阵,有如下操作:
C x1 y1 x2 y2:在区间 [ x1 , y1] ~ [ x2 , y2 ] 的值取反(即1→0, 0→1)
Q x y:查询 点[ x , y ] 的值
思路:
二维树状数组的查找与添加
另一种思路:二维线段树写法
注意:
二维树状数组的更新方式有两种:
1.查询是区间 [ xl, xr ] [yl, yr] ,更新的是点[ x ] [y]
as:在 点[ 2 ][ 4 ] 更新
(更新范围)
[ 2 ] [ 4 ] → [ 2 ] [ n ]
点更新和求和的代码和一维的树状数组一样,查询代码有所不同
比如要查询点[ x1 ] [ y1 ] → 点 [ x2 ] [ y2 ] 的区间:
ans = 0;
for (int i = x1; i <= x2; i++)
ans = ans - sum(i, y1-1) + sum(i, y2);
2.查询的是点 [ x ] [y], 更新的是区间 [ xl, xr ] [yl, yr]
as:在点[ 2 ] [ 3 ] → 点 [ 4 ] [ 5 ] 的区间
(更新范围)
[ 4 ] [ 5 ] → [ n ] [ n ]
[ 4 ] [ 3 ] → [ n ] [ n ]
[ 2 ] [ 5 ] → [ n ] [ n ]
[ 2 ] [ 3 ] → [ n ] [ n ]
区间更新代码:
void add(int x, int y, int d){
int temp = y;
while (x <= final){
y = temp;
while (y <= final){
tree[x][y] += d;
y += lowbit(y);
}
x += lowbit(x);
}
}
在点[ x1 ] [ y1 ] → 点 [ x2 ] [ y2 ] 的区间更新:
add(x2+1, y2+1, 1);
add(x2+1, y1, 1);
add(x1, y2+1, 1);
add(x1, y1, 1);
//or
add(x2+1, y2+1, 1);
add(x1, y2+1, 1);
add(x2+1, y1, 1);
add(x1, y1, 1);
求和的代码:
int sum(int x, int y){
int cnt = 0, temp = y;
while (x > 0){
y = temp;
while (y > 0){
cnt += tree[x][y];
y -= lowbit(y);
}
x -= lowbit(x);
}
return cnt;
}
poj 1195代码
#include <iostream>
using namespace std;
const int MAXN = 1030;
#define lowbit(x) ((x) & -(x))
int tree[MAXN][MAXN];
int final;
void add(int x, int y, int d){
while (y <= final){
tree[x][y] += d;
y += lowbit(y);
}
}
int sum(int x, int y){
int sum = 0;
while (y > 0){
sum += tree[x][y];
y -= lowbit(y);
}
return sum;
}
int main(){
int n, a, b, c, d, ans;
while (~scanf("%d", &n) && n != 3){
if (n == 0){
scanf("%d", &final);
final++;
}
else if (n == 1){
scanf("%d%d%d", &a, &b, &c);
add(a+1, b+1, c);
}
else if (n == 2){
scanf("%d%d%d%d", &a, &b, &c, &d);
a++;
c++;
b++;
d++;
ans = 0;
for ( ; a <= c; a++)
ans = ans - sum(a, b-1) + sum(a, d);
printf("%d\n", ans);
}
}
return 0;
}
poj 2155 代码
#include <iostream>
#include <algorithm>
#include <cstring>
#define lowbit(a) ((a) & (-a))
using namespace std;
const int MAXN = 1010;
int tree[MAXN][MAXN]; //记录取反次数
int final;
void add(int x, int y, int d){
int temp = y;
while (x <= final){
y = temp;
while (y <= final){
tree[x][y] += d;
y += lowbit(y);
}
x += lowbit(x);
}
}
int sum(int x, int y){
int cnt = 0, temp = y;
while (x > 0){
y = temp;
while (y > 0){
cnt += tree[x][y];
y -= lowbit(y);
}
x -= lowbit(x);
}
return cnt;
}
int main(){
int t, m, a, b, c, d;
char op;
scanf("%d", &t);
while (t--){
scanf("%d%d", &final, &m);
memset(tree, 0, sizeof(tree));
while (m--){
scanf(" %c", &op);
if (op == 'C'){
scanf("%d%d%d%d", &a, &b, &c, &d);
add(c+1, d+1, 1);
add(c+1, b, 1);
add(a, d+1, 1);
add(a, b, 1);
}
else{
scanf("%d%d", &a, &b);
printf("%d\n", sum(a, b) % 2);
}
}
printf("\n");
}
return 0;
}