poj2155 Matrix
题目链接:https://vjudge.net/problem/POJ-2155
题意:给出一个全0矩阵,要求支持两种操作:把矩形区域(x1,y1),(x2,y2)的值全部取反(1变成0,0变成1);查询某个点(x,y)的值
其实就是把矩形里的数全部+1,最后询问某个点模2的余数。在一维的区间改单点查里,利用差分转化成单点改区间查,然后用树状数组;在二维的情况下就用二维差分。二维差分定义为d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1],执行区域(x1,y1)到(x2,y2)的加减也可以转化为单点加减:add(x1,y1,1),add(x2+1,y1,-1),add(x1,y2+1,-1),add(x2+1,y2+1),和二维前缀和一样有点容斥的想法。之后再用二维树状数组维护即可
#include<cstdio>
#include<cstring>
using namespace std;
int c[1010][1010],n,q,i,t;
void add(int x,int y,int d){
for (int i=x;i<=n;i+=i&(-i))
for (int j=y;j<=n;j+=j&(-j)) c[i][j]+=d;
}
int ask(int x,int y){
int res=0;
for (int i=x;i>0;i-=i&(-i))
for (int j=y;j>0;j-=j&(-j)) res+=c[i][j];
return res;
}
int main(){
scanf("%d",&t);
while (t--){
memset(c,0,sizeof(c));
scanf("%d%d",&n,&q);
for (i=1;i<=q;i++){
char s[5];
scanf("%s",&s);
if (s[0]=='C'){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
add(x1,y1,1);
add(x2+1,y1,-1);
add(x1,y2+1,-1);
add(x2+1,y2+1,1);
}
else {
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",ask(x,y)%2);
}
}
if (t>0) printf("\n");
}
return 0;
}

浙公网安备 33010602011771号