码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5465 Clarke and puzzle 二维线段树

时间:2015-09-21 17:25:09      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:

Clarke and puzzle

Time Limit: 1 Sec  

Memory Limit: 256 MB

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=5465

Description

克拉克是一名人格分裂患者。某一天,有两个克拉克(aa和bb)在玩一个方格游戏。  
这个方格是一个n*mnm的矩阵,每个格子里有一个数c_{i, j}c?i,j??。  
aa想开挂,想知道如何打败bb。  
他们要玩qq次游戏,每一次做一次操作:  
1. 取出当中的一个子矩阵(x_1, y_1)-(x_2, y_2)(x?1??,y?1??)(x?2??,y?2??)玩游戏。两个人轮流行动,每一次只能从这个子矩阵中的一个方格c_{i, j}c?i,j??中减掉一个的数d(1 \le d \le c_{i, j})d(1dc?i,j??),当一个格子的数为00时则不能减。如果操作完后另一者无法操作,那么胜利。否则失败。现在aa作为先手,想知道是否存在一种方案使得自己胜利。  
2. 将c_{i, j}c?i,j??的数改成bb  

Input

第一行一个整数T(1 \le T \le 5)T(1T5),表示数据的组数。  
每组数据第一行为三个整数n, m, q(1 \le n, m \le 500, 1 \le q \le 2*10^5)n,m,q(1n,m500,1q210?5??)。  
接下来是一个nn行mm列的矩阵,其中第ii行第jj列的数为c_{i, j}(0 \le c_{i, j} \le 10^9)c?i,j??(0c?i,j??10?9??)。  
接下来时qq行,第一个数为optopt。当opt=1opt=1时,后面接着四个整数,依次表示x_1, y_1, x_2, y_2(1 \le x_1 \le x_2 \le n, 1 \le y_1 \le y_2 \le m)x?1??,y?1??,x?2??,y?2??(1x?1??x?2??n,1y?1??y?2??m),表示一个询问;当opt=2opt=2时,后面接着三个整数x, y, z(1 \le x \le n, 1 \le y \le m, 0 \le z \le 10^9)x,y,z(1xn,1ym,0z10?9??),表示将c_{x, y}c?x,y??更改为zz。

Output

对于每组数据,每个询问输出aa是否能胜利,如果能,输出YesYes,否则输出NoNo。  

Sample Input

1
1 2 3
1 2
1 1 1 1 2
2 1 2 1
1 1 1 1 2

Sample Output

Yes
No

HINT

 

题意

 

题解:

题目要求二维的nim游戏,考虑到nim的结论是xor和为0则必败、否则必胜,那么我们只需要维护子矩阵的xor和。由于xor有前缀和性质,所以我们可以用一个二维bit来维护(1, 1)-(a, b)的矩阵的xor和,然后由sum(x2, y2) \ xor \ sum(x2, y1-1) \ xor \ sum(x1-1, y2) \ xor \ sum(x1-1, y1-1)sum(x2,y2) xor sum(x2,y11) xor sum(x11,y2) xor sum(x11,y11)来得到答案即可。单点修改在bit上是很容易的。

技术分享

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MinN = 1010;
struct Nodey
{
    int l,r;
    int val;
};
int locy[MinN],locx[MinN] , n , m, q;

struct Nodex
{
    int l,r;
    Nodey sty[MinN*4];
    void build(int i,int _l,int _r)
    {
        sty[i].l = _l;
        sty[i].r = _r;
        sty[i].val = 0;
        if(_l == _r)
        {
            locy[_l] = i;
            return;
        }
        int mid = (_l + _r)/2;
        build(i<<1,_l,mid);
        build((i<<1)|1,mid+1,_r);
    }
    int queryMin(int i,int _l,int _r)
    {
        if(sty[i].l == _l && sty[i].r == _r)
            return sty[i].val;
        int mid = (sty[i].l + sty[i].r)/2;
        if(_r <= mid)return queryMin(i<<1,_l,_r);
        else if(_l > mid)return queryMin((i<<1)|1,_l,_r);
        else return queryMin(i<<1,_l,mid) ^ queryMin((i<<1)|1,mid+1,_r);
    }
}stx[MinN*4];

void build(int i,int l,int r)
{
    stx[i].l = l;
    stx[i].r = r;
    stx[i].build(1,1,505);
    if(l == r)
    {
        locx[l] = i;
        return;
    }
    int mid = (l+r)/2;
    build(i<<1,l,mid);
    build((i<<1)|1,mid+1,r);
}
//修改值
void Modify(int x,int y,int val)
{
    int tx = locx[x];
    int ty = locy[y];
    stx[tx].sty[ty].val = val;
    for(int i = tx;i;i >>= 1)
        for(int j = ty;j;j >>= 1)
        {
            if(i == tx && j == ty)continue;
            if(j == ty)
            {
                stx[i].sty[j].val = stx[i<<1].sty[j].val ^ stx[(i<<1)|1].sty[j].val;
            }
            else
            {
                stx[i].sty[j].val = stx[i].sty[j<<1].val ^ stx[i].sty[(j<<1)|1].val;
            }
        }
}
int queryMin(int i,int x1,int x2,int y1,int y2)
{
    if(stx[i].l == x1 && stx[i].r == x2)
        return stx[i].queryMin(1,y1,y2);
    int mid = (stx[i].l + stx[i].r)/2;
   // cout << stx[i].l << " " << stx[i].r << " " << mid << endl;
    if(x2 <= mid)return queryMin(i<<1,x1,x2,y1,y2);
    else if(x1 > mid)return queryMin((i<<1)|1,x1,x2,y1,y2);
    else return queryMin(i<<1,x1,mid,y1,y2) ^ queryMin((i<<1)|1,mid+1,x2,y1,y2);
}



int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
    scanf("%d",&T);int m;
    while(T--)
    {
        int q;
        scanf("%d%d",&n,&m);
        scanf("%d",&q);
        build(1,1,505);
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
            {
                int a;
                scanf("%d",&a);
                Modify(i,j,a);
            }

        int x,y,L;
        while(q--)
        {
            int k;scanf("%d",&k);
            if(k==1)
            {
                int x1,x2,y1,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                int ans = queryMin(1,x1,x2,y1,y2);
                if(ans == 0)printf("No\n");else printf("Yes\n");
            }
            else
            {
                int x1,y1,z;scanf("%d%d%d",&x1,&y1,&z);
                Modify(x1,y1,z);
            }
        }
    }
    return 0;
}

 

hdu 5465 Clarke and puzzle 二维线段树

标签:

原文地址:http://www.cnblogs.com/qscqesze/p/4826586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!