题意:给你一个n*n的全0矩阵,每次有两个操作:
C x1 y1 x2 y2:将(x1,y1)到(x2,y2)的矩阵全部值求反
Q x y:求出(x,y)位置的值
树状数组标准是求单点更新区间求和,但是我们处理一下就可以完美解决此问题。区间更新可以使用区间求和的方法,在更新的(x2,y2)记录+1,在更新的(x1-1,y1-1)-1(向前更新到最前方)。单点求和就只需要与区间更新相反,向后求一个区间和。这样做的理由是:如果求和的点在某次更新范围内,我们+1但是不执行-1,否者要么都不执行,要么都执行就不变。
但是这儿我们是二维树状数组,我们需要使用容斥原理:(x2,y2)+1,(x1-1,y2)-1,(x2,y1-1)-1,(x1-1,y1-1)+1
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> #include<algorithm> using namespace std; #define eps 1E-8 /*注意可能会有输出-0.000*/ #define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型 #define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化 #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0 #define mul(a,b) (a<<b) #define dir(a,b) (a>>b) typedef long long ll; typedef unsigned long long ull; const int Inf=1<<28; const double Pi=acos(-1.0); const int Mod=1e9+7; const int Max=1010; int bit[Max][Max],n; void Init(int n) { for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) bit[i][j]=0; return; } int lowbit(int x) { return x&(-x); } void Add(int x,int y,int z) { for(int i=x;i>0;i-=lowbit(i)) { for(int j=y;j>0;j-=lowbit(j)) { bit[i][j]=(bit[i][j]+z+2&1); } } return; } int Sum(int x,int y) { int sum=0; for(int i=x;i<=n;i+=lowbit(i)) { for(int j=y;j<=n;j+=lowbit(j)) { sum+=bit[i][j]; } } return sum & 1; } int main() { int t,q,xx1,xx2,yy1,yy2; char str[10]; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&q); Init(n); while(q--) { scanf("%s",str); if(str[0]=='C') { scanf("%d %d %d %d",&xx1,&yy1,&xx2,&yy2); Add(xx2,yy2,1);//区间更新的容斥原理 Add(xx1-1,yy2,-1); Add(xx2,yy1-1,-1); Add(xx1-1,yy1-1,1); } else { scanf("%d %d",&xx1,&yy1); printf("%d ",Sum(xx1,yy1)); } } if(t) printf(" "); } return 0; }