题意:给定一个0-1矩阵,在线对(x1,y1),(x2,y2)之间的元素置反,在线对特定矩阵求和。
思路:一道二维树状数组,思路还是挺清晰的,由于是0-1矩阵,只需用tre[][]记录一个元素被置反的次数即可,当对(x1,y1),(x2,y2)区间置反时,需要改动四个地方就是4个角就可以了。为什么呢?如下图,假设A区未需要置反的区域,因为改动A区的左上角时,由树状数组的性质知:A,B,C,D4个区域都是要被置反的,所以在依次置反BD,CD,D,这样,置反的总过程为ABCD,BD,CD,D,这样我们就会发现结果对2取模时,只有A区被置反,B,C,D三个区都没有变化。明白原理之后就好做了。
A
|
B
|
C
|
D
|
#include < iostream >
#include < cstdio >
#include < algorithm >
#include < memory.h >
#include < cmath >
#include < bitset >
#include < queue >
#include < vector >
using namespace std;
const int BORDER = ( 1 << 20 ) - 1 ;
const int MAXSIZE = 37 ;
const int MAXN = 1100 ;
const int INF = 1000000000 ;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
int n_tre,n,m;
int tre[MAXN][MAXN];
int lowbit( int x)
{
return x & ( - x);
}
void modify( int x, int y, int delta)
{
for ( int i = x; i <= n_tre; i += lowbit(i))
for ( int j = y; j <= n_tre; j += lowbit(j))
{
tre[i][j] += delta;
}
}
int get_sum( const int & x, const int & y)
{
int sum = 0 ;
for ( int i = x; i > 0 ; i -= lowbit(i))
for ( int j = y; j > 0 ; j -= lowbit(j))
{
sum += tre[i][j];
}
return sum;
}
int init()
{
CLR(tre, 0 );
return 0 ;
}
int input()
{
scanf( " %d%d " , & n, & m);
return 0 ;
}
int work()
{
n_tre = n;
int i,j,tmp,x1,x2,y1,y2;
char s[ 10 ];
while (m -- )
{
scanf( " %s " ,s);
if (s[ 0 ] == ' C ' )
{
scanf( " %d%d%d%d " , & x1, & y1, & x2, & y2);
modify(x1,y1, 1 );
modify(x2 + 1 ,y2 + 1 , 1 );
modify(x1,y2 + 1 , 1 );
modify(x2 + 1 ,y1, 1 );
} else
{
scanf( " %d%d " , & x1, & y1);
printf( " %d\n " ,get_sum(x1,y1) & 1 );
}
}
printf( " \n " );
return 0 ;
}
int main()
{
int tt;
IN(tt);
while (tt -- )
{
init();
input();
work();
}
return 0 ;
}