HDU 5465——Clarke and puzzle——————【树状数组BIT维护前缀和+Nim博弈】
Clarke and puzzle
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 673 Accepted Submission(s): 223
Problem Description
Clarke is a patient with multiple personality disorder. One day, Clarke split into two personality a and b, they are playing a game.
There is a n∗m matrix, each grid of this matrix has a number ci,j.
a wants to beat b every time, so a ask you for a help.
There are q operations, each of them is belonging to one of the following two types:
1. They play the game on a (x1,y1)−(x2,y2) sub matrix. They take turns operating. On any turn, the player can choose a grid which has a positive integer from the sub matrix and decrease it by a positive integer which less than or equal this grid's number. The player who can't operate is loser. a always operate first, he wants to know if he can win this game.
2. Change ci,j to b.
There is a n∗m matrix, each grid of this matrix has a number ci,j.
a wants to beat b every time, so a ask you for a help.
There are q operations, each of them is belonging to one of the following two types:
1. They play the game on a (x1,y1)−(x2,y2) sub matrix. They take turns operating. On any turn, the player can choose a grid which has a positive integer from the sub matrix and decrease it by a positive integer which less than or equal this grid's number. The player who can't operate is loser. a always operate first, he wants to know if he can win this game.
2. Change ci,j to b.
Input
The first line contains a integer T(1≤T≤5), the number of test cases.
For each test case:
The first line contains three integers n,m,q(1≤n,m≤500,1≤q≤2∗105)
Then n∗m matrix follow, the i row j column is a integer ci,j(0≤ci,j≤109)
Then q lines follow, the first number is opt.
if opt=1, then 4 integers x1,y1,x1,y2(1≤x1≤x2≤n,1≤y1≤y2≤m) follow, represent operation 1.
if opt=2, then 3 integers i,j,b follow, represent operation 2.
For each test case:
The first line contains three integers n,m,q(1≤n,m≤500,1≤q≤2∗105)
Then n∗m matrix follow, the i row j column is a integer ci,j(0≤ci,j≤109)
Then q lines follow, the first number is opt.
if opt=1, then 4 integers x1,y1,x1,y2(1≤x1≤x2≤n,1≤y1≤y2≤m) follow, represent operation 1.
if opt=2, then 3 integers i,j,b follow, represent operation 2.
Output
For each testcase, for each operation 1, print Yes if a can win this game, otherwise print No.
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:
The first enquiry: $a$ can decrease grid $(1, 2)$'s number by $1$. No matter what $b$ operate next, there is always one grid with number $1$ remaining . So, $a$ wins.
The second enquiry: No matter what $a$ operate, there is always one grid with number $1$ remaining. So, $b$ wins.
Source
题目大意:给你t组测试数据。每组测试数据中有一组n,m,q,分别表示有一个n*m的矩阵,有q组询问。每组询问中,操作1表示查询(x1,y1) ---(x2,y2)在矩阵中做Nim游戏先手是否会赢。操作2表示要把矩阵中某个值修改为c。
知识补充:对于一维树状数组见的比较多。二维还是见的少(弱)。那么二维跟一维的区别是:一般意义上二维用来求的是矩阵的和。对于C[x][y],这里的定义就是从(1,1)---(x,y)矩阵的元素和。我们可以将每行抽象成一个点,这样其实就是抽象成了求一维的情况。其实一维跟二维实现的写法差别很容易想到。对于二维BIT,我们得到C数组,需要n^2log(n)^2的时间复杂度。
求和:
int sum(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 val){ for(int i=x;i<=n;i+=lowbit(i)){ for(int j=y;j<=m;j+=lowbit(j)){ C[i][j] += val; } } }
解题思路:
#include<bits/stdc++.h> using namespace std; typedef long long INT; const int maxn=550; int a[maxn][maxn]; int C[maxn][maxn]; int n,m; int lowbit(int x){ return x & (-x); } void modify(int x,int y,int val){ for(int i=x;i<=n;i+=lowbit(i)){ for(int j=y;j<=m;j+=lowbit(j)){ C[i][j] ^= val; } } } int sum(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; } int main(){ int t,q; scanf("%d",&t); while(t--){ memset(a,0,sizeof(a)); memset(C,0,sizeof(C)); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ modify(i,j,a[i][j]); } } int typ,x1,x2,y1,y2,c; for(int i=0;i<q;i++){ scanf("%d",&typ); if(typ==1){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); int ans1,ans2,ans3,ans4; ans1=sum(x2,y2); ans2=sum(x2,y1-1); ans3=sum(x1-1,y2); ans4=sum(x1-1,y1-1); int ans=ans1^ans2^ans3^ans4; printf("%s\n",ans==0?"No":"Yes"); }else{ scanf("%d%d%d",&x1,&y1,&c); modify(x1,y1,c^a[x1][y1]); a[x1][y1]=c; } } } return 0; }
学学学 练练练 刷刷刷