Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 26929 | Accepted: 9867 |
Description
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 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
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
这个题暴力肯定是不能过的,这个地方利用了二维树状数组来维护。
不会二维树状数组的请仔细查看博客一维与二维树状数组。
老实说一开始看题解,是怎么也看不懂,实际上树状数组的功能确实没问题,然而在理解上有一些问题。
首先要明确树状数组的板子代表的意思。
假设参数都是x,y,val。
1.updata函数,更新的是a[x][y]的值。
2.ask函数,查询出来的是以(1,1)为左上角以(x,y)为右下角的子矩阵的和!!!!
对于这个题怎么来做呢,这个地方其实是利用了用标记来消除影响的一个效果。
譬如说对于一个1维数组,你要更新区间(l,r)的值,那么你可以让a[l]+val,让a[r+1]-val,这样你从左端加到右端(假设为x)的时候(前缀和)算出来的a[x]的值是正确的。
就是说每一个a[i]的值都是这样得到的a[i]+=a[i-1]。
可以在纸上画一画,便知道了。
然后这个题其实就是把这个方法延伸到了二维上了。
我们更新的是(x1,y1)到(x2,y2)这个子矩阵的值。
那么我们把
1.(x1,y1)+val.
2.(x1,y2+1)-val;
3.(x2+1,y1)-val;
4.(x2+1,y2+1)+val;
这样我们在计算a[x][y]的值的时候,便是从(1,1)端点加到(x,y)端点的值的和了。
表示看了好多题解也没怎么弄懂,最后自己画图终于搞懂了,问了几个也是迷迷糊糊,实际上树状数组的功能很明确就是上面说的。
这个工具到底干了什么,我想很多写出题解的人也不知道吧,这样是无法举一反三的。也无法很好的使用树状数组这个工具。
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=1e5+7;
int n,m,k;
char s[2];
int tu[1005][1005];
int lowbit(int i)
{
return i&(-i);
}
void add(int x,int y,int d)
{
for(int i=x; i<=n; i+=lowbit(i))
for(int j=y; j<=n; j+=lowbit(j))tu[i][j]+=d;
}
int ask(int x,int y)
{
int sum=0;
for(int i=x; i>0; i-=lowbit(i))
for(int j=y; j>0; j-=lowbit(j))sum+=tu[i][j];
return sum;
}
int main()
{
int t;
scanf("%d",&t);
int x1,y1,x2,y2;
while(t--)
{
memset(tu,0,sizeof(tu));
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%s",s);
if(s[0]=='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",&x2,&y2);
int ans=ask(x2,y2);
printf("%d\n",ans%2);
}
}
if(t)puts("");
}
return 0;
}