• bzoj 2819 Nim


    Description

    著名游戏设计师vfleaking,最近迷上了Nim。普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取。谁不能取谁输。这个游戏是有必胜策略的。于是vfleaking决定写一个玩Nim游戏的平台来坑玩家。
    为了设计漂亮一点的初始局面,vfleaking用以下方式来找灵感:拿出很多石子,把它们聚成一堆一堆的,对每一堆编号1,2,3,4,...n,在堆与堆间连边,没有自环与重边,从任意堆到任意堆都只有唯一一条路径可到达。然后他不停地进行如下操作:

    1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家。
    2.把堆v中的石子数变为k。

    由于vfleaking太懒了,他懒得自己动手了。请写个程序帮帮他吧。

    Input

     第一行一个数n,表示有多少堆石子。
    接下来的一行,第i个数表示第i堆里有多少石子。
    接下来n-1行,每行两个数v,u,代表v,u间有一条边直接相连。
    接下来一个数q,代表操作的个数。
    接下来q行,每行开始有一个字符:
    如果是Q,那么后面有两个数v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略。
    如果是C,那么后面有两个数v,k,代表把堆v中的石子数变为k。

    对于100%的数据:
    1≤N≤500000, 1≤Q≤500000, 0≤任何时候每堆石子的个数≤32767
    其中有30%的数据:
    石子堆组成了一条链,这3个点会导致你DFS时爆栈(也许你不用DFS?)。其它的数据DFS目测不会爆。

    注意:石子数的范围是0到INT_MAX

    Soluiton

    因为输入字符的锅搞了几乎一上午。

    题目很简单。

    Nim游戏,先手必胜,Ai异或值不为0,否则必败。

    就是一个路径上的异或和。

    数据范围大,不能树剖。

    发现单点修改。所以可以维护到根节点的异或和。再算上LCA即可。

    树状数组维护dfs序,开始单点修改dfn[i],dfn2[i]+1为a[i]子树外异或两次直接消掉。

    前缀异或值就是到根节点异或值。

    每次单点修改同理。

    然后套个LCA就可以。

    注意,字符输入不要什么ch=getchar()两次,换行符可能很多,还可能有空格。。。。。数据不靠谱。

    直接ch[2] scanf(“%s”,ch) 然后ch[0]==Q多好。直接过滤空格换行符。

    (爆栈?其实不存在的。)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500000+5;
    struct node{
        int nxt,to;
    }e[2*N];
    int hd[N],cnt;
    void add(int x,int y){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        hd[x]=cnt;
    }
    int n,q;
    int f[2*N];
    void xo(int x,int c){
        for(;x<=n;x+=x&(-x)) f[x]^=c;
    }
    int query(int x){
        int ret=0;
        for(;x;x-=x&(-x)) ret^=f[x];
        return ret;
    }
    int dfn[N],df,fdfn[2*N];
    int dfn2[N];
    int a[N];
    int d[N];
    bool fl;
    int fa[N][30];
    int dep[N];
    void dfs(int x,int d){
        dfn[x]=++df;
        fdfn[df]=x;
        dep[x]=d;
        for(int i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==fa[x][0]) continue;
            fa[y][0]=x;
            dfs(y,d+1);
        }
        dfn2[x]=df;
    }
    int lca(int x,int y){
        if(dep[x]<dep[y]) swap(x,y);
        for(int j=25;j>=0;j--){
            if(dep[fa[x][j]]>=dep[y]) 
             x=fa[x][j];
        }
        if(x==y) return x;
        for(int j=25;j>=0;j--){
            if(fa[x][j]!=fa[y][j]){
                x=fa[x][j],y=fa[y][j];
            }
        }
        return fa[x][0];
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int x,y;
        for(int i=1;i<=n-1;i++){
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
            d[x]++,d[y]++;
        }
        scanf("%d",&q);
            dfs(1,1);
            dep[0]=-1;
            for(int j=1;j<=25;j++){
                for(int i=1;i<=n;i++){
                    fa[i][j]=fa[fa[i][j-1]][j-1];
                }
            }
    
            for(int i=1;i<=n;i++){
                xo(dfn[i],a[i]);xo(dfn2[i]+1,a[i]);
            }
            
            
            while(q--){
                char ch[2];
                scanf("%s",ch);
                //cout<<"ch"<<ch<<"|"<<endl;
                scanf("%d %d",&x,&y);
                if(ch[0]=='Q'){
                    int anc=lca(x,y);
                    int lp=query(dfn[x])^query(dfn[y])^a[anc];
                    if(lp==0){
                        printf("No
    ");
                    }
                    else printf("Yes
    ");
                }
                else
                {
                    xo(dfn[x],a[x]);
                    xo(dfn2[x]+1,a[x]);
                    a[x]=y;
                    xo(dfn[x],y);
                    xo(dfn2[x]+1,y);
                }
            }
        return 0;
    }
  • 相关阅读:
    Spring学习02——控制反转、依赖注入
    Spring学习01——HelloSpring
    $(function() {})和$(document).ready(function(){ })
    tomcat 学习
    XML学习
    使用git提交项目至github的标准步骤
    Bootstrap快速入门
    HashMap底层原理及面试问题 [更新中]
    ArrayList remove()元素遇到的问题
    linux 给指定用户分配文件夹权限
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9604688.html
Copyright © 2020-2023  润新知