Xor Path 牛客,HPU--C

题解:

题目要求求出u和v两点在最短路径上的异或和。怎么确定最短路径呢?,就是U到LCA(u,v)的路径加上V到LCA(u,v)。根据异或的性质,如k^a^a=k,即异或一个值两边等于原数值。

所以维护一个数组dp[i]指的是根节点s到点i的异或和,所以答案应该是dp[u]^dp[v]^dp[lca[u,v]]^arr[lca[u,v]]其中arr是每个点的weight.

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1E5+7;
vector<ll >ve[N];
ll arr[N];
bool pre[N];
ll fa[N];
ll dp[N];
ll bits[N];
ll depth[N];
ll father[N][30];
void dfs1(ll x,ll y){//y是x的父亲
    fa[x]=y;
    dp[x]=dp[y]^arr[x];
    for(ll i=0;i<ve[x].size();i++){
        ll c=ve[x][i];
        if(c!=y) {
            dfs1(c,x);
        }
    }
}
void bt()
{
    bits[0]=1;
    for(ll i=1;i<=29;i++) bits[i]=bits[i-1]<<1;
}
void dfs(ll x,ll y){//x是y的儿子节点
    depth[x]=depth[y]+1;
    father[x][0]=y;
    for(ll i=1;i<=29;i++) father[x][i]=father[father[x][i-1]][i-1];
    for(ll i=0;i<ve[x].size();i++){
        ll c=ve[x][i];
        if(c!=y) {
            dfs(c,x);
        }
    }
}
ll lca(ll x,ll y){//设x比y深
    if(depth[x]<depth[y]) swap(x,y);
    ll dif=depth[x]-depth[y];
    for(ll i=29;i>=0;i--){
        if(bits[i]<=dif){
            dif-=bits[i];
            x=father[x][i];
        }
    }
    if(x==y) return x;
    for(ll i=29;i>=0;i--){
        if(depth[x]>=bits[i]&&father[x][i]!=father[y][i]){
            x=father[x][i];
            y=father[y][i];
        }
    }
    return father[x][0];

} 
int main(){
    ll n;
    cin>>n;
    for(ll i=1;i<=n;i++) cin>>arr[i];
    ll x,y;
    for(ll i=1;i<n;i++){
        cin>>x>>y;
        pre[y]=1;
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    bt();
    dfs1(1,0);
    dfs(1,0);
    ll q;
    cin>>q;
    for(ll i=1;i<=q;i++){
        ll x,y;
        cin>>x>>y;
        ll k=dp[x]^dp[y];
        ll a=lca(x,y);
        k=k^arr[a];
        cout<<k<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Accepting/p/12239384.html