Matrix
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]. 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 Source
POJ Monthly,Lou Tiancheng
|
=====================================题目大意=====================================
给出一个元素为0或1的N×M规格的矩阵以及以下操作:
C x1 y1 x2 y2 (1<=x1<=x2<=n,1<=y1<=y2<=n) : 改变左上角为(x1,y1),右下角为(x2,y2)的矩阵中元素的值。
Q x y (1<=x,y<=n) : 查询元素(x,y)的值。
=====================================算法分析=====================================
二维线段树(二维树状数组)。
另外需要注意的是本题中异或的应用。
=======================================代码=======================================
1、二维线段树
#include<stdio.h>
#include<string.h>
#define LSON(N) ((N)<<1 )
#define RSON(N) ((N)<<1|1)
#define MID(L,R) (((L)+(R))>>1)
const int MAXN=1005;
int X,N,T,X1,X2,Y1,Y2;
bool Ans,SegmTree[MAXN<<2][MAXN<<2];
void Build()
{
memset(SegmTree,0,sizeof(SegmTree));
}
void UpdateY(int L,int R,int Nx,int Ny)
{
if(Y1<=L&&R<=Y2)
{
SegmTree[Nx][Ny]^=1;
}
else
{
int M=MID(L,R);
if(Y1<=M) UpdateY(L,M,Nx,LSON(Ny));
if(M<Y2) UpdateY(M+1,R,Nx,RSON(Ny));
}
}
void UpdateX(int L,int R,int Nx)
{
if(X1<=L&&R<=X2)
{
UpdateY(1,N,Nx,1);
}
else
{
int M=MID(L,R);
if(X1<=M) UpdateX(L,M,LSON(Nx));
if(M<X2) UpdateX(M+1,R,RSON(Nx));
}
}
void QueryY(int L,int R,int Nx,int Ny)
{
Ans^=SegmTree[Nx][Ny];
if(L!=R)
{
int M=MID(L,R);
if(Y1<=M) QueryY(L,M,Nx,LSON(Ny));
else QueryY(M+1,R,Nx,RSON(Ny));
}
}
void QueryX(int L,int R,int Nx)
{
QueryY(1,N,Nx,1);
if(L!=R)
{
int M=MID(L,R);
if(X1<=M) QueryX(L,M,LSON(Nx));
else QueryX(M+1,R,RSON(Nx));
}
}
int main()
{
while(scanf("%d",&X)==1) while(X--)
{
Build();
scanf("%d%d",&N,&T);
char order[10];
while(T--)
{
scanf("%s",order);
if(order[0]=='C')
{
scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
UpdateX(1,N,1);
}
else
{
scanf("%d%d",&X1,&Y1);
Ans=0;
QueryX(1,N,1);
printf("%d\n",Ans);
}
}
if(X) printf("\n");
}
return 0;
}
2、二维树状数组
#include<stdio.h>
#include<string.h>
#define LOWBIT(N) ((N)&(-(N)))
const int MAXN=1005;
int X,N,T,X1,X2,Y1,Y2;
bool Ans,BinTree[MAXN<<2][MAXN<<2];
void Build()
{
memset(BinTree,0,sizeof(BinTree));
}
void Update(int X,int Y)
{
for(int i=X;i<=N;i+=LOWBIT(i))
{
for(int j=Y;j<=N;j+=LOWBIT(j))
{
BinTree[i][j]^=1;
}
}
}
void GetAns(int X,int Y)
{
for(int i=X;i;i-=LOWBIT(i))
{
for(int j=Y;j;j-=LOWBIT(j))
{
Ans^=BinTree[i][j];
}
}
}
int main()
{
while(scanf("%d",&X)==1) while(X--)
{
Build();
scanf("%d%d",&N,&T);
char order[10];
while(T--)
{
scanf("%s",order);
if(order[0]=='C')
{
scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
Update(X1,Y1); Update(X2+1,Y1);
Update(X1,Y2+1); Update(X2+1,Y2+1);
}
else
{
scanf("%d%d",&X1,&Y1);
Ans=0;
GetAns(X1,Y1);
printf("%d\n",Ans);
}
}
if(X) printf("\n");
}
return 0;
}