题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5465
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define read(x,y) scanf("%d%d",&x,&y)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn =1e3+5;
const int mod=1e9+7;
/*
题目大意:博弈背景,给定一个方阵,
然后两种操作,一种是询问子矩阵,另一种是修改矩阵中的权值。
对于每次询问子矩阵,判断博弈结果,
博弈的规则是可以选方阵中的一个正数,并减去一个不大于选择数的数字。
其实就是普通的Nim游戏,最终是判断子矩阵的异或和。
下面就是二维树状数组裸题目了,
维护的是子矩阵异或和,因为异或操作也满足区间性质所以可以维护。
修改的时候别忘了在原来的数据域上也修改。
我犯 的一个错误是用long long 来参与位运算,结果出问题了。
其实看一下数据域不会超过int,因为全部异或的话最大是最大值的两倍。
*/
///树状数组结构
int n,m,q;
int x1,y1,x2,y2;
int tree[maxn][maxn],dat[maxn][maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y,ll d)
{
int tmp=y;
while(x<=n)
{
for(int p=tmp;p<=m;tree[x][p]^=d,p+=lowbit(p));
x+=lowbit(x);
}
}
int sum(int x,int y)
{
int ret=0;
int tmp=y;
while(x)
{
for(int p=tmp;p>0;ret^=tree[x][p],p-=lowbit(p));
x-=lowbit(x);
}
return ret;
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
memset(tree,0,sizeof(tree));
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&dat[i][j]);
add(i,j,dat[i][j]);
}
for(int i=0,op;i<q;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int ret=sum(x2,y2)^sum(x2,y1-1)^sum(x1-1,y2)^sum(x1-1,y1-1);///用long long 做位运算会出问题
if(ret) puts("Yes");
else puts("No");
}
else
{
scanf("%d%d%d",&x1,&y1,&x2);
add(x1,y1,(dat[x1][y1]^x2));
dat[x1][y1]=x2;
}
}
}
return 0;
}