图片说明
介绍两种思路,一种被卡掉了
注意一下这个异或和是指 所有path(i,j)的异或

首先从一个根出发,算出跟到点x的路径异或为b[x]

那么对于两点的path(i,j)的答案即为:b[x]^b[y]^a[lca]

由于最终答案又是异或 也就是说path(i,j)表示为三个数异或然后在异或

显然对于每一个点而言,要异或其他n-1个点 ,也就是说该点在最终答案中b[i]出现次数是n-1次

所以首先看一下n的奇偶,如果为偶数首先把所有的b[i]异或起来

之后看一下a[u],a[u]就是作为lca异或的次数

通过dfs计算就可以了,判断奇偶性

Code:

/*** keep hungry and calm CoolGuang!***/
///#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pp;
const ll INF=1e17;
const int Maxn=1e6+10;
const int maxn =2e6+10;
const int mod= 1e9+7;
const int Mod = 1e6+7;
///const double eps=1e-10;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
struct node{
    int e,next;
}edge[maxn];
ll cnt = 0;
int head[maxn];
void addedge(int u,int v){
    edge[cnt] = node{v,head[u]};
    head[u] = cnt++;
}
ll a[maxn],b[maxn];
void dfs(int u,int fa,ll w){
    b[u] = a[u]^w;
    for(int i=head[u];~i;i=edge[i].next){
        int e = edge[i].e;
        if(e == fa) continue;
        dfs(e,u,a[u]^w);
    }
}
ll sz[maxn];
ll ans = 0;
void dfs(int u,int fa){
    sz[u] = 1;
    ll res = 0;
    for(int i=head[u];~i;i=edge[i].next){
        int e = edge[i].e;
        if(e == fa) continue;
        dfs(e,u);
        res += sz[u] * sz[e];
        sz[u] += sz[e];
    }
    if(res&1) ans ^= a[u];
}

int main()
{
    read(n);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n-1;i++){
        int x,y,z;scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    for(int i=1;i<=n;i++) read(a[i]);
    dfs(1,1,0);
    dfs(1,1);
    ///debug(ans);
    if(!(n&1))
        for(int i=1;i<=n;i++) ans^=b[i];
    printf("%lld\n",ans);
    return 0;
}
/**
1000

**/

另外附带一个常数的做法:
这种问题我首先想到的是按位拆开
但是可能这个题把这个常数给卡掉了..
复杂度:32*n

/*** keep hungry and calm CoolGuang!***/
///#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string>
#include<iostream>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pp;
const ll INF=1e17;
const int Maxn=1e6+10;
const int maxn =2e6+10;
const int mod= 1e9+7;
const int Mod = 1e6+7;
///const double eps=1e-10;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
struct node{
    int e,next;
}edge[maxn];
ll cnt = 0;
int head[maxn];
void addedge(int u,int v){
    edge[cnt] = node{v,head[u]};
    head[u] = cnt++;
}
ll a[maxn],b[maxn];
void dfs(int u,int fa,ll w){
    b[u] = a[u]^w;
    for(int i=head[u];~i;i=edge[i].next){
        int e = edge[i].e;
        if(e == fa) continue;
        dfs(e,u,a[u]^w);
    }
}
ll sz[maxn][2];
ll res[105];
void TraceBack(int u,int fa,int bit){
    int op = (b[u]>>bit&1)?1:0;
    sz[u][op] = 1;
    sz[u][!op] = 0;
    int opt = (a[u]>>bit&1)?1:0;
    for(int i=head[u];~i;i=edge[i].next){
        int e = edge[i].e;
        if(e == fa) continue;
        TraceBack(e,u,bit);
        if(!opt) res[bit] += sz[e][0]*sz[u][1]+sz[e][1]*sz[u][0];
        else res[bit] += sz[e][0]*sz[u][0]+sz[e][1]*sz[u][1];
        sz[u][0] += sz[e][0];
        sz[u][1] += sz[e][1];
    }
}

int main()
{
    read(n);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n-1;i++){
        int x,y,z;scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    for(int i=1;i<=n;i++) read(a[i]);
    dfs(1,1,0);
    for(int i=0;i<=31;i++) TraceBack(1,1,i);
    ll ans = 0;
    for(int i=0;i<=31;i++)
            if(res[i]&1)
                ans |= 1ll<<i;
    printf("%lld\n",ans);
    return 0;
}
/**
1000

**/