题目:http://poj.org/problem?id=2155
题意:有一个n*n矩阵,一开始每个格上都是0,两种操作:1)C x1 y1 x2 y2,把左上角为x1,y1,右下角为x2,y2的矩形范围的格子反转,0变1,1变0;2)Q x y,问x,y这个格子现在是0还是1
思路:
想了好久的二维树状数组。。。。
考虑一维翻转区间[ i,j ]的情况:
更新:
首先i <= x <= n翻转次数cnt[ x ] 都加1,等价于第 i 项的值加1后,前 i 项的和加1,前i+1项的和加1……前n项的和加1
再让 j+1 <= x <= n翻转次数加1。
求和:
那么求cnt[x]就是求前x项之和。
如此转化为树状数组问题。
二维时:
求i,j的翻转次数cnt[ i ][ j ],等于前 i 行前 j 列之和
翻转的范围为x1,y1,x2,y2,那么相当于翻转:
1)x1,y1,n,n;
2)x1, y2 + 1,n,n;
3)x2 + 1, y1,n,n;
4)x2 + 1,y2 + 1,n,n
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#define INF 0x7fffffff
#define MOD 1000000007
using namespace std;
typedef long long ll;
int n;
int bit[1005][1005];
int sum(int x,int y)
{
int ans=0;
for(int i=x;i>0;i-=(i & -i))
for(int j=y;j>0;j-=(j & -j))
{
ans+=bit[i][j];
}
return ans;
}
void change(int x,int y)
{
for(int i=x;i<=n;i+=(i & -i))
for(int j=y;j<=n;j+=(j & -j))
{
bit[i][j]+=1;
//printf("bit[%d][%d]=%d\n", i, j, bit[i][j]);
}
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int cas, t;
char c;
scanf("%d", &cas);
while(cas--)
{
scanf("%d%d", &n, &t);
memset(bit, 0, sizeof(bit));
for(int i = 0; i < t; i++)
{
scanf(" %c", &c);
if(c == 'C')
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
change(x1, y1);
change(x1, y2 + 1);
change(x2 + 1, y1);
change(x2 + 1, y2 + 1);
}
else
{
int x, y;
scanf("%d%d", &x, &y);
//printf("x=%d y=%d\n", x, y);
printf("%d\n", sum(x, y) % 2);
}
}
printf("\n");
}
return 0;
}