题目链接: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 ",ask(x,y)%2); } } if (t>0) printf(" "); } return 0; }