1 条题解

  • 0
    @ 2025-8-24 21:43:58

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar lizbaka
    「道阻且长,行而未至」

    搬运于2025-08-24 21:43:58,当前版本为作者最后更新于2018-08-29 22:23:08,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    关于Nim游戏,sg函数及其一些变形可以戳这位大佬的blog:

    https://blog.csdn.net/clover_hxy/article/details/53818624


    Solution

    这是一道阶梯Nim游戏的题,与普通的阶梯Nim游戏不同之处在于它是在一棵树上移动,实际上就是多个阶梯Nim游戏的复合

    我们知道,阶梯Nim游戏可以视作对奇数阶梯上上的石子做Nim,证明在上方的blog中有提及,在此不再赘述

    在此题中,设11号节点的深度为00,那么深度为奇数的节点即为“奇数阶梯”

    考虑每次对节点上石头数量的修改,我们可以保存上一次修改后求出的sgsg值的异或和xx

    如果修改的节点的深度为偶数,对答案并没有贡献,直接判断上一次的xx即可

    如果修改的节点的深度为奇数,由于异或满足自反性(即xx xor xx =0=0),所以在修改之前,我们只需要对xx异或一遍修改前的数,再异或一遍修改后的数即可,而没有必要重新求一遍异或和

    Code

    #include <cstdio>
    #define maxn 10005
    #define maxL 1005
    using namespace std;
    
    int n,T,L;
    int r[maxn],prt[maxn],dep[maxn];
    int sg[maxL];
    
    int x;
    inline bool Solve(int pos,int chg)
    {
        if(!(dep[pos]&1))
            return x;
        x^=sg[r[pos]];
        x^=sg[r[pos]=chg];
        return x;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&T,&L);
        register int i;
        int a,b;
        for(i=1;i<=1000;++i)
            sg[i]=i%(L+1);
        for(i=2;i<=n;++i)
        {
            scanf("%d%d",&prt[i],&r[i]);
            dep[i]=dep[prt[i]]+1;
            if(dep[i]&1)
                x^=sg[r[i]];
        }
        for(i=1;i<=T;++i)
        {
            scanf("%d%d",&a,&b);
            if(Solve(a,b))
                printf("Yes\n");
            else
                printf("No\n");
        }
        return 0;
    }
    
    
    
    • 1

    信息

    ID
    2037
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者