• 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 nm 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(1T5), the number of test cases. 
    For each test case: 
    The first line contains three integers n,m,q(1n,m500,1q2105) 
    Then nm matrix follow, the i row j column is a integer ci,j(0ci,j109) 
    Then q lines follow, the first number is opt
    if opt=1, then 4 integers x1,y1,x1,y2(1x1x2n,1y1y2m) 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
    ",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;
    }
    

      

     
     
  • 相关阅读:
    Linux下静态库与动态库
    通过js操作样式(评分)
    javascript学习
    2017年6月1日学习
    javascript学习2
    javascript学习:闭包和prototype原型使用基础
    关于“System.Data.ProviderIncompatibleException”类型的异常
    Android性能优化之ViewStub
    Activity Threa创建Window和View分析
    软键盘触发后弹起底部布局文件方法
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4832894.html
Copyright © 2020-2023  润新知