bestcoder #56 div 2 C Clarke and puzzle (nim游戏 树状数组)

Clarke and puzzle

Accepts: 129

Submissions: 322

Time Limit: 4000/2000 MS (Java/Others)

Memory Limit: 65536/65536 K (Java/Others)

问题描述

克拉克是一名人格分裂患者。某一天,有两个克拉克(aa和bb)在玩一个方格游戏。
这个方格是一个n*mn∗m的矩阵,每个格子里有一个数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(1≤d≤c?i,j??),当一个格子的数为00时则不能减。如果操作完后另一者无法操作,那么胜利。否则失败。现在aa作为先手,想知道是否存在一种方案使得自己胜利。
2. 将c_{i, j}c?i,j??的数改成bb  

输入描述

第一行一个整数T(1 \le T \le 5)T(1≤T≤5),表示数据的组数。
每组数据第一行为三个整数n, m, q(1 \le n, m \le 500, 1 \le q \le 2*10^5)n,m,q(1≤n,m≤500,1≤q≤2∗10?5??)。
接下来是一个nn行mm列的矩阵,其中第ii行第jj列的数为c_{i, j}(0 \le c_{i, j} \le 10^9)c?i,j??(0≤c?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??(1≤x?1??≤x?2??≤n,1≤y?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(1≤x≤n,1≤y≤m,0≤z≤10?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游戏所以这是一个二维的nim游戏.nim游戏的性质是xor 和为0必败,否则必胜.xor和也有前缀和性质,所以可以用树状数组维护.

  1 /*************************************************************************
  2     > File Name: code/bc/#56/r1003.cpp
  3     > Author: 111qqz
  4     > Email: [email protected]
  5     > Created Time: 2015年09月22日 星期二 11时10分06秒
  6  ************************************************************************/
  7
  8 #include<iostream>
  9 #include<iomanip>
 10 #include<cstdio>
 11 #include<algorithm>
 12 #include<cmath>
 13 #include<cstring>
 14 #include<string>
 15 #include<map>
 16 #include<set>
 17 #include<queue>
 18 #include<vector>
 19 #include<stack>
 20 #include<cctype>
 21 #define y1 hust111qqz
 22 #define yn hez111qqz
 23 #define j1 cute111qqz
 24 #define ms(a,x) memset(a,x,sizeof(a))
 25 #define lr dying111qqz
 26 using namespace std;
 27 #define For(i, n) for (int i=0;i<int(n);++i)
 28 typedef long long LL;
 29 typedef double DB;
 30 const int inf = 0x3f3f3f3f;
 31 const int N=5E2+5;
 32 int c[N][N];
 33 int a[N][N];
 34 int n,m,q;
 35 int lowbit ( int x)
 36 {
 37     return x&(-x);
 38 }
 39 void update (int x,int y,int delta)
 40 {
 41     for ( int i = x ; i <= n ; i = i + lowbit(i))
 42     {
 43     for ( int j =  y ;  j <= m ; j = j + lowbit(j))
 44     {
 45         c[i][j]^=delta;
 46     }
 47     }
 48 }
 49
 50 int sum( int x,int y)
 51 {
 52     int res = 0;
 53     for ( int i = x; i >= 1 ; i = i - lowbit(i))
 54     {
 55     for ( int j = y ; j >= 1 ; j = j - lowbit(j))
 56     {
 57         res ^= c[i][j];
 58     }
 59     }
 60     return res;
 61 }
 62 int main()
 63 {
 64   #ifndef  ONLINE_JUDGE
 65    freopen("in.txt","r",stdin);
 66   #endif
 67
 68    int T;
 69    scanf("%d",&T);
 70    while (T--)
 71     {
 72     ms(c,0);
 73
 74     scanf("%d %d %d",&n,&m,&q);
 75     for ( int i = 1 ; i <= n ; i++)
 76     {
 77         for ( int j = 1 ; j <= m ; j++)
 78         {
 79         scanf("%d",&a[i][j]);
 80         update (i,j,a[i][j]);
 81         }
 82     }
 83
 84     for (int  i = 0 ; i < q ; i++)
 85     {
 86         int opt;
 87         scanf("%d",&opt);
 88         if (opt==1)
 89         {
 90         int x1,x2,y1,y2;
 91         scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
 92         int tmp = sum(x2,y2)^sum(x2,y1-1)^sum(x1-1,y2)^sum(x1-1,y1-1);
 93         if (tmp>0)
 94         {
 95             puts("Yes");
 96         }
 97         else
 98         {
 99             puts("No");
100         }
101         }
102         else
103         {
104         int x,y,z;
105         scanf("%d %d %d",&x,&y,&z);
106         update (x,y,a[x][y]); //清零
107         a[x][y] = z;
108         update (x,y,a[x][y]);
109         }
110     }
111     }
112
113
114  #ifndef ONLINE_JUDGE
115   fclose(stdin);
116   #endif
117     return 0;
118 }


时间: 2024-08-28 16:33:03

bestcoder #56 div 2 C Clarke and puzzle (nim游戏 树状数组)的相关文章

Codeforces Round 261 Div.2 D Pashmak and Parmida&#39;s problem --树状数组

题意:给出数组A,定义f(l,r,x)为A[]的下标l到r之间,等于x的元素数.i和j符合f(1,i,a[i])>f(j,n,a[j]),求有多少对这样的(i,j). 解法:分别从左到右,由右到左预处理到某个下标为止有多少个数等于该下标,用map维护. 然后树状数组更新每个f(j,n,a[j]),预处理完毕,接下来,从左往右扫过去,每次从树状数组中删去a[i],因为i != j,i不能用作后面的统计,然后统计getsum(inc[a[i]]-1), (inc表示从左到右),即查询比此时的a[i]

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*mn∗m的矩阵,每个格子里有一

CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)

转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有出现偶数次的数异或的值. 思路:容易想到,把区间内的所有的数都异或得到的是出现奇数次的数的值,然后再异或该区间内的所有出现过的数(每个数只统计一次),得到的ans了. 第一个问题:得到询问区间的

CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组

题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有出现偶数次的数异或的值. 思路:容易想到,把区间内的所有的数都异或得到的是出现奇数次的数的值,然后再异或该区间内的所有出现过的数(每个数只统计一次),得到的ans了. 第一个问题:得到询问区间的所有数的异或值,由 a[l~r] ^ a[0~(l-1)] = a[l~r] 可以用数组all_xor[i

Codeforces Round #424 (Div. 2) D 思维 E set应用,树状数组

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) D. Office Keys 题意:一条直线上,有个办公室坐标 p,有 n个人在a[i],有 k把钥匙在b[i],每个人必须拿到一把钥匙,然后到办公室.问怎么安排花的时间最短. tags:还是不懂套路啊..其实多画两下图就能够感觉出来,2333 关键是要看出来,n个人拿的 n把钥匙应该是连续的. 然后,就是瞎暴力.. #include<bits/stdc++.h> usi

Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)

题目链接:http://codeforces.com/contest/703/problem/D 给你n个数,m次查询,每次查询问你l到r之间出现偶数次的数字xor和是多少. 我们可以先预处理前缀和Xor[i],表示1~i的xor和.因为num^num=0,所以Xor[r] ^ Xor[l - 1]求的是l~r之间出现奇数次的数字xor和. 那怎么求偶数次的呢,那我们可以先求l到r之间不重复出现数字的xor(比如1 1 2 求的是1 ^ 2),然后再xor以上求出的Xor[r] ^ Xor[l

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以

Codeforces Round #301 (Div. 2) E. Infinite Inversions —— 逆序对 离散化 + 树状数组

题目链接:http://codeforces.com/contest/540/problem/E E. Infinite Inversions time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output There is an infinite sequence consisting of all positive integers in

Codeforces Round #285 (Div.1 B &amp; Div.2 D) Misha and Permutations Summation --二分+树状数组

题意:给出两个排列,求出每个排列在全排列的排行,相加,模上n!(全排列个数)得出一个数k,求出排行为k的排列. 解法:首先要得出定位方法,即知道某个排列是第几个排列.比如 (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0). 拿排列(1,2,0)来说,首位是1,前面有cnt=1个小于1的没被用过的数(0),所以它的排行要加上(cnt=1)*2!,第二位为2,因为1已经放了,所以小于2的只有0了,即cnt=1个,所以,排