[BZOJ2819]Nim

Nim

题目大意

给你一棵树,实现两个操作:

1、改变制定点的权值

2、问用一条链上的所有点的权值做nim游戏,有没有必胜策略。

Solution

首先nim游戏的必胜策略:当前状态所有值异或和不是0

感性理解:每次我选择一个堆然后改变它使得异或和变成0

然后下一个玩家玩的时候不可能使异或和依旧保持0,所以就不可能变成全空的状态

那么我们用树状数组,在dfn[x]处异或上x,在dfn[x]+siz[x]处也异或上x,这样就发现在x子树内的点都异或了x而在x子树外的就没有异或x(大概是差分?)

修改的时候直接改,然后查询的时候就查询从根到x节点的链的异或和和从根到y的节点的异或和,然后从根到lca这段就相当于没有异或,但我们还要把lca的权值也给异或上

code:

#include<bits/stdc++.h>
using namespace std;
inline int lowbit(int x){return x&-x;}
int c[500010];
int n;
void update(int x,int v){
    while(x<=n+1){
        c[x]^=v;
        x+=lowbit(x);
    }
}
int query(int x){
    int ans=0;
    while(x){
        ans^=c[x];
        x-=lowbit(x);
    }
    return ans;
}
struct qwq{
    int v;
    int nxt;
}edge[1000010];
int head[500010];
int cnt=-1;
void add(int u,int v){
    edge[++cnt].nxt=head[u];
    edge[cnt].v=v;
    head[u]=cnt;
}
int dfn[500010];
int siz[500010];
int ind;
int f[500010][21];
int dep[500010];
void dfs(int u,int fa){
    for(int i=1;i<=20;++i){
        f[u][i]=f[f[u][i-1]][i-1];
    }
    siz[u]=1;
    dfn[u]=++ind;
    for(int i=head[u];~i;i=edge[i].nxt){
        int v=edge[i].v;
        if(v==fa)continue;
        f[v][0]=u;
        dep[v]=dep[u]+1;
        dfs(v,u);
        siz[u]+=siz[v];
    }
}
int lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    int deep=dep[x]-dep[y];
    for(int i=0;i<=20;++i){
        if(deep&(1<<i)){
            x=f[x][i];
        }
    }
    if(x==y)return x;
    for(int i=20;i>=0;--i){
        if(f[x][i]!=f[y][i]){
            x=f[x][i],y=f[y][i];
        }
    }
    return f[x][0];
}
int val[500010];
int main(){
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&val[i]);
    }
    for(int i=1;i<n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs(1,0);
    for(int i=1;i<=n;++i){
        update(dfn[i],val[i]);
        update(dfn[i]+siz[i],val[i]);
    }
    int m;
    scanf("%d",&m);
    int mm=m;
    char ch[1];
    for(int i=1;i<=mm;++i){
        scanf("%s",ch);
        if(ch[0]=='Q'){
            int x,y;
            scanf("%d%d",&x,&y);
            int LCA=lca(x,y);
            int tmp=query(dfn[x])^query(dfn[y])^val[LCA];
            if(tmp)puts("Yes");
            else puts("No");
        }
        else {
            int x,v;
            scanf("%d%d",&x,&v);
            update(dfn[x],val[x]);
            update(dfn[x]+siz[x],val[x]);
            val[x]=v;
            update(dfn[x],val[x]);
            update(dfn[x]+siz[x],val[x]);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/youddjxd/p/11619334.html