zoukankan      html  css  js  c++  java
  • XOR path|LCA最近公共祖先,树链异或和

    题目描述

    补题记录

    思路:DFS计算从根节点到每个节点的异或和,同时计算倍增。
    然后利用倍增可以实现O(logn)的查询。

    #include<bits/stdc++.h>
    using namespace std;
    
    /*
    思路: 
    	DFS计算从根节点到每个节点的异或和,同时计算倍增。
    	然后利用倍增可以实现O(logn)的查询。
    */ 
    
    /*
    小结: 
    	学会了树上异或和的lca优化方法、还需要熟悉和理解lca原理 
    */ 
    
    const int N = 1e6+100;
    vector<int> G[N];
    int pre[N],a[N],par[N];
    long long bit[30];
    int f[N][30];
    int depth[N];
    
    //初始化 
    void init(){
    	bit[0]=1;
    	for(int i=1;i<=29;i++) bit[i]=(bit[i-1]<<1);
    }
    
    //倍增
    void dfs(int u,int par){
    	depth[u]=depth[par]+1;
    	f[u][0]=par;
    	for(int i=1;bit[i]<=depth[u];i++) f[u][i]=f[f[u][i-1]][i-1];
    	for(int v:G[u]){
    		if(v!=par) dfs(v,u);
    	}
    }
    
    //lca
    int lca(int x,int y){
    	if(depth[x]<depth[y]) swap(x,y);
    	for(int i=29;i>=0;i--){
    		if(depth[x]-depth[y]>=bit[i]){
    			x=f[x][i];
    		}
    	}
    	if(x==y) return x;
    	for(int i=29;i>=0;i--){
    		if(depth[x]>=(1<<i)&&f[x][i]!=f[y][i]){
    			x=f[x][i];
    			y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    
    //从根节点1出发 求每个点到根节点的路径异或和 
    void DFS1(int u,int fa){
        par[u]=fa;
        pre[u]=pre[fa]^a[u];
        for(int v:G[u]){
            if(v==fa) continue;
            DFS1(v,u);
        }
    }
    
    int main(){
        int n,u,v,q;
        cin>>n;
        init();
        //建图 邻接表 
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=0;i<=n;i++) G[i].clear();
        for(int i=1;i<=n-1;i++){
            cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        //lca
        dfs(1,0);
        //计算从根节点到每个结点的异或和 
        DFS1(1,0);
        int x,y;
        cin>>q;
        while(q--){
            cin>>x>>y;
            int c=lca(x,y); //lca求出最近公共祖先 
            int f=par[c]; //求出最近公共祖先的父节点  这里再求一次父节点的原因是: 消除祖先的父节点到根节点这段路径(异或了2次)的异或 
            cout<<(pre[x]^pre[f]^pre[c]^pre[y])<<endl; //画图理解 树链上异或两次就等于没有异或  
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    游戏类型
    cocos2d-x lua 一些语法
    lua中ipairs和pairs
    lua的一些语法
    误删jre怎么办
    右键android工程的包名选择Build Path后怎么还原
    播放Armature动画
    接入第三方sdk出现了一些问题总结
    gettimeofday() 获取系统时间,精确到微秒 这个似乎只能在linux 下用,不能在windows 下用
    windows timeGetTime() 函数 获取系统从开机到现在的毫秒时间值
  • 原文地址:https://www.cnblogs.com/fisherss/p/12104680.html
Copyright © 2011-2022 走看看