zoukankan      html  css  js  c++  java
  • [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
    ",#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
    ",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的。

  • 相关阅读:
    Qt音视频开发8-ffmpeg保存裸流
    Qt音视频开发7-ffmpeg音频播放
    Qt音视频开发6-ffmpeg解码处理
    Qt音视频开发5-vlc事件订阅
    Qt音视频开发4-vlc读取和控制
    Qt音视频开发3-vlc录像存储
    Qt音视频开发2-vlc回调处理
    Qt音视频开发1-vlc解码播放
    【日拱一卒】链表——两个有序的链表合并
    osg计算线段与球面的交点
  • 原文地址:https://www.cnblogs.com/hankeke/p/Luogu2420-xor.html
Copyright © 2011-2022 走看看