题解Luogu P2972 [USACO10HOL]岩石和树木Rocks and Trees

Posted lizbaka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解Luogu P2972 [USACO10HOL]岩石和树木Rocks and Trees相关的知识,希望对你有一定的参考价值。

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

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


Solution

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

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

在此题中,设(1)号节点的深度为(0),那么深度为奇数的节点即为“奇数阶梯”

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

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

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

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
");
        else
            printf("No
");
    }
    return 0;
}

以上是关于题解Luogu P2972 [USACO10HOL]岩石和树木Rocks and Trees的主要内容,如果未能解决你的问题,请参考以下文章

[Luogu2973][USACO10HOL]赶小猪

Luogu2973 [USACO10HOL]Driving Out the Piggies G

[USACO10HOL]赶小猪题解

[Luogu P2973&BZOJ 1778][USACO10HOL]赶小猪DOtP(高斯消元+期望)

「LCA」[USACO10HOL]牛的政治Cow Politics

COGS——T 803. [USACO Hol10] 政党 || 1776: [Usaco2010 Hol]cowpol 奶牛政坛