[Luogu2420]让我们异或吧

原题链接https://www.luogu.org/problem/show?pid=2420

题解:
简单地看一下,是非常裸的求树上路径问题。自然就知道用LCA。
不过,首先我们得知道所谓的“异或交换律”和“异或结合律”,类似于加法交换结合律。因此我们不论怎么分路径,最终合并起来的结果与按顺序来的一样。
比如说,( a xor b ) xor c = a xor ( b xor c ) a xor b = b xor a 这些东西。因此,我们假如我们想要求 a xor b xor c xor d xor e ,可以转换为 ( a xor b ) xor ( e xor d xor c )

#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(i,a,n) for(register int i=a;i<=n;++i)
#define per(i,a,n) for(register int i=a;i>=n;--i)
#define debug(x) printf("debug:%s=%d\n",#x,x)
#define fec(i,x) for(register int i=head[x];i;i=Next[i])
template<typename A>inline void read(A&a){char c=0;A f=1;a=0;while(c<'0'||c>'9'){c=getchar();if(c=='-')f*=-1;}while(c>='0'&&c<='9')a=a*10+c-'0',c=getchar();a*=f;}
template<typename A,typename B>inline void read(A&a,B&b){read(a);read(b);}
template<typename A,typename B,typename C>inline void read(A&a,B&b,C&c){read(a);read(b);read(c);}

const int maxn=100000+7,LOG=20-1;

int u[maxn<<1],v[maxn<<1],w[maxn<<1],head[maxn],Next[maxn<<1],tot;
void addedge(int x,int y,int z){
	u[++tot]=x;v[tot]=y;w[tot]=z;
	Next[tot]=head[x];head[x]=tot;
}

int n,x,y,z,visit[maxn],depth[maxn],f[maxn][LOG],dist[maxn][LOG],q;

void dfs(int x){
	visit[x]=1;
	depth[x]=depth[f[x][0]];
	rep(i,1,LOG-1)f[x][i]=f[f[x][i-1]][i-1],dist[x][i]=dist[x][i-1]^dist[f[x][i-1]][i-1];
	fec(i,x){
		if(visit[v[i]])continue;
		f[v[i]][0]=x;
		dist[v[i]][0]=w[i];
		dfs(v[i]);
	}
}

int LCA(int x,int y){
	if(depth[x]<depth[y])swap(x,y);
	int ans=0;
	per(i,LOG-1,0)if(depth[f[x][i]]<=depth[y])ans^=dist[x][i],x=f[x][i];
	if(x==y)return ans;
	per(i,LOG-1,0)if(f[x][i]!=f[y][i])ans^=dist[x][i]^dist[y][i],x=f[x][i],y=f[y][i];
	return ans^dist[x][0]^dist[y][0];
}
 
void Init(){
	read(n);
	rep(i,1,n-1){
		read(x,y,z);
		addedge(x,y,z);
		addedge(y,x,z);
	}
}

void Work(){
	dfs(1);
	read(q);
	rep(i,1,q){
		read(x,y);
		printf("%d\n",LCA(x,y));
	}
}

int main(){
//	freopen("temp.in","r",stdin);
	Init();
	Work();
	return 0;
}

深入思考一下可以发现,两次xor同一个数,就会保持不变。即m xor n xor n = m。因此,我们可以直接从那两个点分别走到根节点,记录下分别的总xor的值,再一起xor一下,那么重复的值就会因为两次xor而xor掉。虽然这样时间复杂度会高一点但是代码好些多了,而且这样的时间也是可以Accepted的。

posted @ 2017-07-31 17:46  hankeke303  阅读(233)  评论(0编辑  收藏  举报