以前看树状数组总觉得很难,到现在看回来其实本质不过是一个简单的高校维护前缀和的小工具,也不必掌握差分,区间修改老老实实用线段数会比较直观。
两个要注意的地方
- 数组下标要从一开始
- 数状数组适用于一切满足结合律的运算 如乘法、加法、异或
奉上我的数状数组板子
poj 2155 http://poj.org/problem?id=2155
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i=a; i<=b; i++)
#define drep(i, a, b) for (int i=b; i>=a; i--)
typedef long long ll;
using namespace std;
const int maxn=1010;
struct BIT {
int a[maxn][maxn];
inline int lowbit(int x) {
return x & (-x);
}
void init() {
for (int i=0; i<maxn; i++)
memset(a[i], 0, sizeof(a[i]));
}
/*一维数状数组,init函数自行修改一下即可
void modify(int x,int add) {
while (x <= n) {
a[x] += add;
x += lowbit(x);
}
}
int get_sum(int x) {
int ret = 0;
while (x != 0) {
ret += a[x];
x -= lowbit(x);
}
return ret;
}
*/
void modify(int x, int y, int data) {
for (int i = x; i < maxn; i += lowbit(i))
for (int j = y; j < maxn; j += lowbit(j))
a[i][j] += data;
}
int query(int x, int y) {
int res = 0;
for (int i = x; i > 0; i -= lowbit(i))
for (int j = y; j > 0; j -= lowbit(j))
res += a[i][j];
return res;
}
}s;
int main() {
int test, x1, y1, x2, y2, n , m;
char str[4];
for(scanf("%d", &test); test--; ){
scanf("%d%d", &n, &m);
s.init();
while(m--){
scanf("%s%d%d", str, &x1, &y1);
if(str[0] == 'C'){
scanf("%d%d", &x2, &y2);
x1++; y1++; x2++; y2++;
s.modify(x2, y1-1, 1);
s.modify(x1-1, y2, 1);
s.modify(x1-1, y1-1, 1);
s.modify(x2, y2, 1);
}
else puts(s.query(x1, y1) & 1 ? "1" : "0");
}
puts("");
}
return 0;
}