链接
http://poj.org/problem?id=2155
题意
给你一个
n
×
n
n\times n
n×n的矩阵,现在让你对它进行
k
k
k次操作,共两种,第一种是告诉你
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
(x1,\ y1),(x2,\ y2)
(x1, y1),(x2, y2),对于
x
1
≤
x
≤
x
2
x1\leq x\leq x2
x1≤x≤x2及
y
1
≤
y
≤
y
2
y1\leq y\leq y2
y1≤y≤y2的
(
x
,
y
)
(x,\ y)
(x, y),进行反转,即原来是1的变为0,是0的变为1,第二种是查询一个
(
x
,
y
)
(x,\ y)
(x, y)的值;
分析
使用树状数组;对于一维的树状数组,考虑一维上的对于 [ l , r ] [l,r] [l,r]区间同时加上x,我们使用树状数组的操作是在 l l l加上 x x x,在 r + 1 r+1 r+1加上一个 − x -x −x,求位置 y y y的值直接求 s u m ( y ) sum(y) sum(y)即可;另外,使用这种方法的前提是差分的思想,一般情况下我们的数组初始化都是为0,所以差分之后还是0,所以我们默认的是我们的操作都是基于差分的操作(这句话的意思是,如果你有一个非零的序列,你要使用树状数组给它某个区间进行加上某个值的操作,你必须求出它的差分数组,然后对差分数组操作);
那么考虑二维树状数组,对于一个矩形区域的反转,我们将它视为给改矩形区域都加上一个1的操作,当我们需要求某个点 ( x , y ) (x,\ y) (x, y)值的时候,我们就直接二维 s u m ( x , y ) sum(x,\ y) sum(x, y),类似一维时候的正常操作,对于这个求出来的值假设是 P P P,那么这个 P P P的意义就是我们对 ( x , y ) (x,\ y) (x, y)这个点进行反转操作的次数,对于反转操作来说,它只有两种可能要么是0要么是1,而初始的时候是0,反转奇数次一定是1,偶数次一定是0,所以我们只需要把我们求得的 ( x , y ) (x,\ y) (x, y)位置的反转次数 P P P除以2就可以了;
这里就省略了具体怎么对矩形区域的加1操作,还需要注意0的 l o w b i t lowbit lowbit无意义,所以代码中有了++的操作;
代码
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#define INF 0x7f7f7f7f
#define MAXN 1000005
#define N 200005
#define P 2
#define MOD 99991
typedef long long ll;
namespace fastIO {
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
//char buf[(1 << 22)], *p1 = buf, *p2 = buf;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
}
using namespace fastIO;
using namespace std;
int q, n, t, c[1006][1011];
void insert(int x, int y) {
for (int i = x; i <= n + 3; i += i & -i)
for (int j = y; j <= n + 3; j += j & -j)
c[i][j]++;
}
int sum(int x, int y) {
if (x <= 0 || y <= 0)return 0;
int res = 0;
for (int i = x; i > 0; i -= i & -i)
for (int j = y; j > 0; j -= j & -j)
res += c[i][j];
return res&1;
}
int main() {
q = read();
while (q--) {
n = read(), t = read();
char o[2]; int x1, y1, x2,y2;
memset(c, 0, sizeof(c));
for (int i = 1; i <= t; i++) {
scanf("%s", o);
if (o[0] == 'C') {
x1 = read(), y1 = read(), x2 = read(), y2 = read();
x1++, x2++, y1++, y2++;
insert(x1, y1);
insert(x1, y2 + 1);
insert(x2 + 1, y1);
insert(x2 + 1, y2 + 1);
}
else {
x1 = read(), y1 = read();
x1++, y1++;
printf("%d\n", sum(x1, y1));
}
}
printf("\n");
}
}