zoukankan      html  css  js  c++  java
  • 【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]);
    		}
    	}
    }
    
  • 相关阅读:
    使用SuperWebSocket 构建实时 Web 应用
    slam for Windows 库安装及应用libfreenect2
    《SLAM十四讲》g2o_custombundle在windows轻松调通
    windows下命令行查看库依赖
    zend studio控制台中文乱码
    http协议转
    mysql 字段 增删改
    PHP内部函数
    分层设计
    SecureCRT上传和下载
  • 原文地址:https://www.cnblogs.com/youddjxd/p/11619334.html
Copyright © 2011-2022 走看看