题意:给了一个初始值全部为0的数组,有两种指令,C和Q,C是更改(x1,y1)到(x2,y2)范围内的数值,如果是0则改为1,如果是1则改为0。【题目称之为翻转】,Q是查询(x,y)的数值。
这是一个二维数组的区间更新和单点查询的题目,sum和update方法相对于一维的树状数组增加了一个循环。需要注意的地方是,树状数组只能更新(1,1)到(x,y)的数值,所以在更新(x1,y1)到(x2,y2)范围内时,先翻转(1,1)到(x2,y2)范围内,再将除去(x1,y1)和(x2,y2)的范围再翻转一次。c数组用来记录的是翻转次数。该位置的数值就是该位置c数组的数值mode2。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int c[1005][1005],n;
int lowbit(int i)
{
return i&(-i);
}
int sum(int x,int y)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
for(int j=y;j>0;j-=lowbit(j))
{
ans+=c[i][j];
}
return ans;
}
void update(int x,int y,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
{
c[i][j]+=k;
}
}
int main()
{
int casen,t;
scanf("%d",&casen);
while(casen--)
{
memset(c,0,sizeof(c));
scanf("%d%d",&n,&t);
getchar();
for(int i=0;i<t;i++)
{
int x1,y1,x2,y2;
char ch;
scanf("%c",&ch);
if(ch=='C')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
update(x1,y1,1);
update(x1,y2+1,1);
update(x2+1,y1,1);
update(x2+1,y2+1,1);
getchar();
}
else
{
int a,b;
scanf("%d%d",&a,&b);
getchar();
printf("%d\n",sum(a,b)%2);
}
}
printf("\n");
}
}
这题我被挂了一个多小时。。就因为sum方法中更新j的时候lowbit传的参数是i,这些错误要杜绝掉的啊嘞。。。。。真是。。。浪费好久