hdu 5465 Clarke and puzzle 树状数组

来源:互联网 发布:php程序员的工作日常 编辑:程序博客网 时间:2024/04/29 12:31
克拉克是一名人格分裂患者。某一天,有两个克拉克(aabb)在玩一个方格游戏。  这个方格是一个nmnm的矩阵,每个格子里有一个数cijci,jaa想开挂,想知道如何打败bb。  他们要玩qq次游戏,每一次做一次操作:  1. 取出当中的一个子矩阵x1y1x2y2(x1,y1)(x2,y2)玩游戏。两个人轮流行动,每一次只能从这个子矩阵中的一个方格cijci,j中减掉一个的数d1dcijd(1dci,j),当一个格子的数为00时则不能减。如果操作完后另一者无法操作,那么胜利。否则失败。现在aa作为先手,想知道是否存在一种方案使得自己胜利。  2. 将cijci,j的数改成bb  
输入描述
第一行一个整数T1T5T(1T5),表示数据的组数。  每组数据第一行为三个整数nmq1nm5001q2105n,m,q(1n,m500,1q2105)。  接下来是一个nnmm列的矩阵,其中第ii行第jj列的数为cij0cij109ci,j(0ci,j109)。  接下来时qq行,第一个数为optopt。当opt1opt=1时,后面接着四个整数,依次表示x1y1x2y21x1x2n1y1y2mx1,y1,x2,y2(1x1x2n,1y1y2m),表示一个询问;当opt2opt=2时,后面接着三个整数xyz1xn1ym0z109x,y,z(1xn,1ym,0z109),表示将cxycx,y更改为zz
输出描述
对于每组数据,每个询问输出aa是否能胜利,如果能,输出YesYes,否则输出NoNo
输入样例
11 2 31 21 1 1 1 22 1 2 11 1 1 1 2
输出样例
YesNo
Hint
第一个询问:一开始aa可以在12(1,2)的格子上减掉11,则接下来无论bb怎么选,都还剩一个11,所以aa胜利。第二个询问:无论aa怎么选,都还剩下一个11,所以bb胜利。
题目要求二维的nim游戏,考虑到nim的结论是xor和为0则必败、否则必胜,那么我们只需要维护子矩阵的xor和。由于xor有前缀和性质,所以我们可以用一个二维bit来维护(1, 1)-(a, b)的矩阵的xor和,然后由sumx2y2 xor sumx2y11 xor sumx11y2 xor sumx11y11sum(x2,y2) xor sum(x2,y11) xor sum(x11,y2) xor sum(x11,y11)来得到答案即可。单点修改在bit上是很容易的。
#include <cstdio>#include <cstring>using namespace std;int T, n, m, q;int c[600][600];int num[600][600];int lowbit(int x){    return x & (-x);}  int query(int x, int y){    int ret = 0;    for (int i = x; i > 0; i -= lowbit(i))    {        for (int j = y; j > 0; j -= lowbit(j))        {            ret ^= c[i][j];        }    }    return ret;}void modify(int x, int y, int delta){    for (int i = x; i <= n; i += lowbit(i))    {        for (int j = y; j <= m; j += lowbit(j))        {            c[i][j] ^= delta;        }    }}int main(){    scanf("%d", &T);    while(T--)    {        scanf("%d%d%d", &n, &m, &q);        memset(num, 0, sizeof(num));        memset(c, 0, sizeof(c));        for (int i = 1; i <= n; i++)            for (int j = 1; j <= m; j++)            {                scanf("%d", &num[i][j]);                modify(i, j, num[i][j]);            }        int opt, x1, y1, x2, y2;        int x, y, z;        for (int i = 1; i <= q; i++)        {            scanf("%d", &opt);            if (opt == 1)            {                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);                int ans = query(x2, y2) ^ query(x1 - 1, y1 - 1) ^ query(x2, y1 - 1) ^ query(x1 - 1, y2);                //printf("<%d>\n", ans);                if (ans == 0)                    printf("No\n");                else                     printf("Yes\n");            }            else             {                scanf("%d%d%d", &x, &y, &z);                modify(x, y, z ^ num[x][y]);                num[x][y] = z;            }        }    }    return 0;}


0 0
原创粉丝点击