当前位置: 代码迷 >> 综合 >> HDU 5465 Clarke and puzzle (二维树状数组水题+基础博弈)
  详细解决方案

HDU 5465 Clarke and puzzle (二维树状数组水题+基础博弈)

热度:43   发布时间:2023-11-15 15:49:35.0

题目链接: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;
}