BZOJ P2819 Nim

来源:互联网 发布:10年nba总决赛数据 编辑:程序博客网 时间:2024/04/28 01:01

要求某一个路径上的xor和

我们知道xor的一个性质a xor b xorb =a

也就是一个数xor两边之后其实是抵消掉的

知道了这个性质我们开始下面的分析

若两个点在同一条路径上,那么我们假设为x,y然后x是y的祖先

然后我们直接亦或一下x到根的亦或和和y到根的亦或和就知道了x到y的儿子的亦或和

因为y算了两遍,此时直接再亦或上一个y就可以得到x到y的亦或和了

x,y不在一条路径上的话直接求一下lca就可以了

这代码能A算我输

#include<iostream>#include<fstream>#include<algorithm>#include<cmath>#include<cstring>using namespace std;int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='0')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}int bin[23];int n,m,cnt;int t[500003];int tim,l[500003],r[500003],val[500003];int last[500003],deep[500005],f[500003][23];struct edge{int to,next;}e[1000005];void insert(int u,int v){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void add(int x,int val){for(int i=x;i<=n;i+=i&-i){t[i]^=val;}}int query(int x){int fanhui=0;for(int i=x;i;i-=i&-i){fanhui^=t[i];}return fanhui;}void dfs(int x){l[x]=++tim;for(int i=last[x];i;i=e[i].next){if(e[i].to!=f[x][0]){deep[e[i].to]=deep[x]+1;f[e[i].to][0]=x;dfs(e[i].to);}}r[x]=tim;}bool pd(int a,int b){if(l[a]<=l[b]&&r[a]>=r[b]){return true;}else{return false;}}int lca(int x,int y){if(pd(x,y))return x;if(pd(y,x))return y;int k=x;for(int i=20;i>=0;i--){if(!pd(f[k][i],y)){k=f[k][i];}}return f[k][0];}int main(){bin[0]=1;for(int i=1;i<=20;i++){bin[i]=bin[i-1]<<1;}n=read();for(int i=1;i<=n;i++){val[i]=read();}for(int i=1;i<n;i++){int u=read(),v=read();insert(u,v);}dfs(1);f[1][0]=1;for(int i=1;i<=20;i++){for(int j=1;j<=n;j++){f[j][i]=f[f[j][i-1]][i-1];}}for(int i=1;i<=n;i++){add(l[i],val[i]);add(r[i]+1,val[i]);}m=read();while(m--){char ch;cin>>ch;int x=read(),y=read();if(ch=='Q'){int t=lca(x,y);int res=query(l[x])^query(l[y])^val[t];if(res==1){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}}else{add(l[x],val[x]);add(r[x]+1,val[x]);val[x]=y;add(l[x],y);add(r[x]+1,y);}}return 0;}/*in:51 3 5 2 51 53 52 51 46Q 1 2Q 3 5C 3 7Q 1 2Q 2 4Q 5 3out:YesNoYesYesYes*/


1 0
原创粉丝点击