http://poj.org/problem?id=2155
题意:操作C表示让左上角为(x1,y1)右下角为(x2,y2)的矩形内所有的01取反,一开始的时候全部为0。Q询问(x,y)内是0还是1。
这道题可以把01取反看成是操作C的累加,如果某个单元被操作了奇数次,那么相当于取反,否则就是没有动。这道题和一维情况中改变区间查询点的情况类似,只是将一维升级成二维。如果现在要改变左上角为(x1,y1)右下角为(x2,y2)的矩形,那么只要给一个二维数组中(x1,y1)(x2+1,y2+1)(x1,y2+1)(x1+1,y2)全部加上1,以(x1,y1)为例,在查询(x,y)的时候,通过累加,会把以(1,1)为左上角,(x,y)为右下角的矩形中所有的数加起来,那么如果(x1,y1)在这范围内,对(x,y)而言,就被操作了一次。综合起来,就是把以(x1,y1)为左上角,(n,n)为右下角的矩形内01取反。同理,其他也是一样的。最后相互抵消后,相当于是让左上角为(x1,y1)右下角为(x2,y2)的矩形内所有的01取反。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1005
using namespace std;
int n;
char s[3];
int c[N][N];
int lowbit(int x)
{
return x&(-x);
}
void change(int x, int y, int d)
{
int i = y;
while(x <= n)
{
y = i;
while(y <= n)
{
c[x][y] += d;
c[x][y] %= 2;
y += lowbit(y);
}
x += lowbit(x);
}
}
int query(int x, int y)
{
int i = y, sum = 0;
while(x > 0)
{
y = i;
while(y > 0)
{
sum += c[x][y];
sum %= 2;
y -= lowbit(y);
}
x -= lowbit(x);
}
return sum;
}
int main()
{
int T, m, ans, x, y, x2, y2, x1, y1;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
memset(c, 0, sizeof(c));
for (int i = 1; i <= m; i++)
{
scanf("%s", &s);
if (s[0] == 'C')
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
change(x2+1, y2+1, 1);
change(x1, y2+1, 1);
change(x2+1, y1, 1);
change(x1, y1, 1);
}
if (s[0] == 'Q')
{
scanf("%d%d", &x, &y);
ans = query(x, y);
printf("%d\n", ans);
}
}
if (T) printf("\n");
}
return 0;
}