• BZOJ2819: Nim


    题解:nim博弈 把问题转化成 求一条链上异或和是否为0 这样的话最直观的写法就是熟练剖分+BIT了  但是考虑到异或的性质 我们可以构造差分维护子树 用lca解决问题 复杂度只有一个log 但是我比qko的2个log还慢TAT

    #include <bits/stdc++.h>
    const int MAXN=5e5+10;
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    int n,q;
    int a[MAXN];
    vector<int>vec[MAXN];
    int dep[MAXN],fa[MAXN],num[MAXN],son[MAXN];
    int p[MAXN];
    int cnt;
    void dfs1(int v,int pre,int deep){
        p[v]=++cnt;fa[v]=pre;num[v]=1;dep[v]=deep+1;
        for(int i=0;i<vec[v].size();i++){
    	if(vec[v][i]!=pre){
    	    dfs1(vec[v][i],v,deep+1);
    	    num[v]+=num[vec[v][i]];
    	    if(son[v]==-1||num[son[v]]<num[vec[v][i]])son[v]=vec[v][i];
    	}
        }
    }
    int tp[MAXN];
    void dfs2(int v,int td){
        tp[v]=td;
        if(son[v]!=-1)dfs2(son[v],td);
        for(int i=0;i<vec[v].size();i++){
    	if(son[v]!=vec[v][i]&&fa[v]!=vec[v][i])dfs2(vec[v][i],vec[v][i]);
        }
    }
    int d[MAXN];
    int get_id(int x){return x&(-x);}
    void add(int x,int vul){
        for(int i=x;i<=n;i+=get_id(i))d[i]^=vul;
    }
    int Lca(int u,int v){
        int uu=tp[u];int vv=tp[v];
        while(uu!=vv){
    	if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
    	u=fa[uu];uu=tp[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        return u;
    }
    int Sum(int x){
        int ans=0;
        for(int i=x;i>0;i-=get_id(i))ans^=d[i];
        return ans;
    }
    int main(){
        n=read();
        for(int i=1;i<=n;i++)a[i]=read(),son[i]=-1;
        int u,v;
        for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
        dfs1(1,0,0);
      //  cout<<"sb"<<endl;
        dfs2(1,1);
       // cout<<"sb"<<endl;
       // for(int i=1;i<=n;i++)cout<<p[i]<<" ";
       // cout<<endl;
        for(int i=1;i<=n;i++)add(p[i],a[i]),add(p[i]+num[i],a[i]);
       // cout<<"sb"<<endl;
        int q;q=read();char ch;
        for(int i=1;i<=q;i++){
    	scanf(" %c",&ch);
    	if(ch=='Q'){
    	    u=read(),v=read();int lca=Lca(u,v);
    //	    cout<<lca<<endl;
    //	    cout<<p[u]<<" "<<p[v]<<endl;
    	    int t=Sum(p[u])^Sum(p[v]);
    //	    cout<<t<<endl;
    	    t^=a[lca];
    //	    cout<<t<<" "<<a[lca]<<endl;
    	    if(t)puts("Yes");
    	    else puts("No");
    	}
    	else{
    	    u=read();v=read();
    	    add(p[u],a[u]);add(p[u]+num[u],a[u]);
    	    add(p[u],v);add(p[u]+num[u],v);
    	    a[u]=v;
    	}
        }
    }
    

    2819: Nim

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 3605  Solved: 1354
    [Submit][Status][Discuss]

    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

    Output

    对于每个Q,输出一行Yes或No,代表对询问的回答。

    Sample Input

    【样例输入】
    5
    1 3 5 2 5
    1 5
    3 5
    2 5
    1 4
    6
    Q 1 2
    Q 3 5
    C 3 7
    Q 1 2
    Q 2 4
    Q 5 3

    Sample Output

    Yes
    No
    Yes
    Yes
    Yes

     

  • 相关阅读:
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之sonarqube配置
    Abp vnext 配置Swagger增加token认证
    sonarqube+gitlab runner +docker 代码质量检查问题汇总
    【EF Core】EF core中使用FluentAPI对外键进行指定配置
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之gitlab runner 关于私有docker仓库配置
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之harbor
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之gitlab + gitlab runner(docker in docker)
    【杂记】关于在实际项目中使用TDD的方法
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之docker+docker compose
    【TeamCity】使用TeamCity搭建ASP.NET Core + SVN 的 CICD环境
  • 原文地址:https://www.cnblogs.com/wang9897/p/9216084.html
Copyright © 2020-2023  润新知