Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1 <= i, j <= N).
We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.
1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).
2. Q x y (1 <= x, y <= n) querys A[x, y].
Input
The first line of the input is an integer X (X <= 10) representing the number of test cases. The following X blocks each represents a test case.
The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2 y2", which has been described above.
Output
For each querying output one line, which has an integer representing A[x, y].
There is a blank line between every two continuous test cases.
Sample Input
1
2 10
C 2 1 2 2
Q 2 2
C 2 1 2 1
Q 1 1
C 1 1 2 1
C 1 2 1 2
C 1 1 2 2
Q 1 1
C 1 1 2 1
Q 2 1
Sample Output
1
0
0
1
Translate
有一个N*N的矩阵,元素值只可能是0或1。现在有两种操作:
1.C x1 y1 x2 y2:将矩形(x1,y1,x2,y2)的元素全部取反。
2.Q x y:查询(x,y)处的值。
输入数据:
第一行给出测试数据的组数X,接下来有X组数据,每组数据的第一行有两个整数N和T。N表示矩阵的边长,T表示操作的次数。N<=1000,T<=50000.接下来T行操作,如上所示。
输出数据:
对于每组数据的每次查询,输出一个整数,表示查询的结果。
思路:
这道题是区间更改,单点查询。
区间更改与树状数组的单点更改不同,所以我们用二维差分把它变成单点更改。
一维差分:
已知区间(x1,x2)加v
C[x1]+=v; C[x2+1]-=v;
那么二维差分:
和一维差分差不多, 每一次给定 左上角 (x1,y1),右下角 (x2,y2)加v
C[x1][y1] += v, C[x2 + 1][y2 + 1] += v , C[x1][y2 + 1] -= v , C[x2 + 1][y1] -= v;
之后再用二维前缀和,就是将之前的数字全部相加,那这道题相当于单点更改,区间查询了。
因为这题只有0,1,数字代表翻转次数,奇数次即为翻转,偶数次为未翻转,这里的+1,-1是一个意思(改变奇偶),所以这道题就不需要区分加减了。
代码:
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
#include<string.h>
#include<iostream>
#define ll long long
int val[2100][2100];
int n;
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
for(int i=x; i<=n; i+=lowbit(i)) //二维树状数组的代码
{
for(int j=y; j<=n; j+=lowbit(j))
{
val[i][j]++;
}
}
}
int getsum(int x,int y)
{
int ans=0;
for(int i=x; i; i-=lowbit(i))
{
for(int j=y; j; j-=lowbit(j))
{
ans+=val[i][j];
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int m;
scanf("%d %d",&n,&m);
char a[10];
int x1,y1,x2,y2;
memset(val,0,sizeof(val));
for(int i=1; i<=m; i++)
{
scanf("%s",a);
if(a[0]=='C')
{
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
add(x1,y1);
add(x1,y2+1);
add(x2+1,y1);
add(x2+1,y2+1);
}
else
{
scanf("%d %d",&x1,&y1);
printf("%d\n",getsum(x1,y1)%2);
}
}
if(t!=0)
printf("\n");
}
}