POJ 2155 Matrix (树状数组)

题意:给定一个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;
}

原文地址:https://www.cnblogs.com/lvpengms/p/1719133.html