CF341D-Iahub and Xors
题目
一个\(n\times n\)的零矩阵\(a\),\(m\)次操作:
- \(x_0\ y_0\ x_1\ y_1\ c\),对\(a[x][y],x\in[x_0,x_1],y\in[y_0,y_1]\)异或上一个数\(c\)
- \(x_0\ y_0\ x_1\ y_1\),询问这个子矩阵的异或和
\(n\le 1000,m\le 10^5,0\le c<2^{62}\)。
分析
树状数组的妙用!关键还是在异或的性质和处理矩阵的方法。
首先考虑矩阵异或,单点查询,那么对于一个修改\((x_0,y_0,x_1,y_1,c)\),如果我们对\((x_0,y_0),(x_0,y_1+1),(x_1+1,y_0),(x_1+1,y_1+1)\)都异或上\(c\),那么一个结论就是一个点\((x,y)\)的值就是\((1,1,x,y)\)的异或和。(画一画图就知道了)
现在是询问子矩阵的异或和,显然首先转化为求任意的\((1,1,x,y)\)的异或和。
在之前那种修改方式下,一个点的点值就是\((1,1,x,y)\)的异或和,那么要求\((1,1,x,y)\)的异或和,我们就把这些异或和异或起来。
考虑每个点的出现次数,我们会发现,对于一个点\((x_0,y_0)\),它在总异或中出现奇数次当且仅当\((x-x_0+1)(y-y_0+1)\)为奇数。
例如我们统计\((1,1,3,4)\)的异或和的异或和,我们只用统计\((1,2),(1,4),(3,2),(3,4)\)这几个点的值。
于是对于每一种\((x,y)\)的奇偶情况,我们开一个二维树状数组来进行单点修改,前缀异或和查询即可(二维树状数组就是一维树状数组的每个点都是一个树状数组)。
代码
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long giant;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=1e3+2;
int n,m;
inline int lowbit(int x) {return x&-x;}
struct BIT {
giant c[maxn][maxn];
void change(int x,int y,giant d) {
for (;x<=n+1;x+=lowbit(x)) for (int i=y;i<=n+1;i+=lowbit(i)) c[x][i]^=d;
}
giant query(int x,int y) {
giant ret=0;
for (;x;x-=lowbit(x)) for (int i=y;i;i-=lowbit(i)) ret^=c[x][i];
return ret;
}
} t[2][2];
giant get(int x,int y) {
giant ret=t[x&1][y&1].query((x+1)>>1,(y+1)>>1);
}
giant get(int x1,int y1,int x2,int y2) {
giant a=get(x1-1,y1-1);
giant b=get(x1-1,y2);
giant c=get(x2,y1-1);
giant d=get(x2,y2);
giant ret=a^b^c^d;
return ret;
}
void change(int x,int y,giant c) {
t[x&1][y&1].change((x+1)>>1,(y+1)>>1,c);
}
void change(int x1,int y1,int x2,int y2,giant c) {
change(x1,y1,c);
change(x1,y2+1,c);
change(x2+1,y1,c);
change(x2+1,y2+1,c);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read(),m=read();
while (m--) {
int o=read(),x1=read(),y1=read(),x2=read(),y2=read();
giant c;
if (o==2) scanf("%lld",&c);
if (o==1) printf("%lld\n",get(x1,y1,x2,y2)); else change(x1,y1,x2,y2,c);
}
return 0;
}