Matrix
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 27601 | Accepted: 10077 |
Description
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].
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.
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.
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
Source
给定一个 N*N 的矩阵,初始值全为0。给出两种共 T 个操作。一种是给定两个点的坐标,这两个点围城的矩形内的点取反(1变成0,0变成1)。一种是给定一个点的坐标,问这个点是 1 还是 0。
这是一个经典的二维树状数组的问题。
首先,注意到这是一个 0 1 变换的问题。一个点变换两次等于没有变换。因此,我们只需要知道这个点更新了多少次,就知道这个点最后的状态了。
对于每一个取反操作,只需要对矩形的四个角的变换次数加一(左闭右开)。这时,对于矩形内部的点,加了1,变换有效。对于矩形外部的点,加了 0 或 2,变换无效。最后,利用二维树状数组维护区间变换次数。对于每个点求其区间上的前缀和就好了。
令外,关于二维树状数组可以这样理解。
先把普通二维数组的每一行都构造成一维树状数组。然后把每一行看成一个元素,构造成一列树状数组,元素对应相加。
(例如:第二行树状数组中的每一个元素 = 原第一行 + 原第二行)。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1000 + 10;
int Bit[maxn][maxn];
int N, T;
int X;
void Add(int x, int y, int t)
{
for(int i= x; i<= N; i+= i&-i)
for(int j= y; j<= N; j+= j&-j)
Bit[i][j] += t;
}
int Sum(int x, int y)
{
int res = 0;
for(int i= x; i; i-= i&-i)
for(int j= y; j; j-= j&-j)
res += Bit[i][j];
return res;
}
int main()
{
scanf(" %d", &X);
while(X--)
{
memset(Bit, 0, sizeof(Bit));
scanf("%d %d", &N, &T);
for(int i= 1; i<= T; i++)
{
char c;
int x1, y1, x2, y2;
scanf(" %c", &c);
if(c == 'C')
{
scanf(" %d %d %d %d", &x1, &y1, &x2, &y2);
Add(x1, y1, 1);
Add(x1, y2+1, 1);
Add(x2+1, y1, 1);
Add(x2+1, y2+1, 1);
}
else
{
scanf("%d %d", &x1, &y1);
int res = Sum(x1, y1);
printf("%d\n", res & 1);
}
}
cout << endl;
}
return 0;
}