【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]);
		}
	}
}
posted @ 2019-10-03 11:01  FakeDragon  阅读(166)  评论(0编辑  收藏  举报