HDU 5465 Clarke and puzzle Nim游戏+二维树状数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5465 Clarke and puzzle Nim游戏+二维树状数组相关的知识,希望对你有一定的参考价值。

题目链接:

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

Clarke and puzzle

 
 Accepts: 42
 
 Submissions: 269
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
克拉克是一名人格分裂患者。某一天,有两个克拉克(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  
输入描述
第一行一个整数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。
输出描述
对于每组数据,每个询问输出aa是否能胜利,如果能,输出YesYes,否则输出NoNo。  
输入样例
1
1 2 3
1 2
1 1 1 1 2
2 1 2 1
1 1 1 1 2
输出样例
Yes
No
Hint
第一个询问:一开始aa可以在(1, 2)(1,2)的格子上减掉11,则接下来无论bb怎么选,都还剩一个11,所以aa胜利。
第二个询问:无论aa怎么选,都还剩下一个11,所以bb胜利。

题解:

  Nim游戏有个结论:只要所有的数异或为零,则先手必败。因此我们只要用二维树状数组来维护二维区间的所有数的异或值就可以了。

 

代码:

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 typedef long long LL; 
 7 
 8 const int maxn=555;
 9 
10 int lowbit(int x){
11     return x&-x;
12 }
13 
14 int n,m,q;
15 int a[maxn][maxn];
16 int c[maxn][maxn];
17 
18 void update(int x,int y,int v){
19     for(int i=x;i<=n;i+=lowbit(i)){
20         for(int j=y;j<=m;j+=lowbit(j)){
21             c[i][j]^=v;
22         }
23     }
24 }
25 
26 int query(int x,int y){
27     int ret=0;
28     for(int i=x;i>0;i-=lowbit(i)){
29         for(int j=y;j>0;j-=lowbit(j)){
30             ret^=c[i][j];
31         }
32     }
33     return ret;
34 }
35 
36 void init(){
37     memset(c,0,sizeof(c));
38 }
39 
40 int main(){
41     int tc;
42     scanf("%d",&tc);
43     while(tc--){
44         init();
45         scanf("%d%d%d",&n,&m,&q);
46         
47         for(int i=1;i<=n;i++){
48             for(int j=1;j<=m;j++){
49                 int v;
50                 scanf("%d",&v);
51                 a[i][j]=v;
52                 update(i,j,v);
53             }
54         }
55         int op;
56         while(q--){
57             scanf("%d",&op);
58             if(op==1){
59                 int x1,y1,x2,y2;
60                 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
61                 int ans=query(x2,y2)^query(x1-1,y2)^query(x2,y1-1)^query(x1-1,y1-1);
62                 //两次异或相当于减,所以这里相当于是:query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1),容斥的思想; 
63                 if(ans) printf("Yes\n");
64                 else printf("No\n");
65             }else{
66                 int x,y,v;
67                 scanf("%d%d%d",&x,&y,&v);
68                 update(x,y,v^a[x][y]); 
69                 a[x][y]=v;
70             }
71         }
72     }
73     return 0;
74 } 
View Code

 

 

以上是关于HDU 5465 Clarke and puzzle Nim游戏+二维树状数组的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5627Clarke and MST

hdu 5626 Clarke and points

HDU 5464 Clarke and problem 动态规划

hdu 5564 Clarke and digits 矩阵快速幂优化数位dp

HDU 5564 Clarke and digits 状压dp+矩阵加速

hdu5628 Clarke and math