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

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值