Dis
Title description:
Given a tree of n points, each point has its own point weight, ask the XOR sum of the point set formed by the simple path of two points multiple times.
Ideas:
Doubling on the tree at a glance to find the XOR of the LCA maintenance path
fa[i][j]
Indicates the 2 jth pointi
going up from the beginning
fuck[i][j]
Represents the XOR sum of the point weights of 2 ii
points from the beginningThe process of maintaining the fuck array can be maintained in the process of seeking LCA
It should be noted that when running LCA
- If the sum is in the same chain, the answer at the end
x
is not counted, we need to judge and calculatey
x=y
- If it is not in the same chain, when running LCA, x and y will end up at the next layer node of LCA, which is
x-lca-y
a situation formed. We have not calculated the values of these three, and we need to calculate them specially.
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 1000000 + 50
int a, b;
int n, m;
int ar[MAX];
int tot;
int head[MAX];
struct ran{
int to, nex;
}tr[MAX];
void add(int u, int v){
tr[++tot].to = v;
tr[tot].nex = head[u];
head[u] = tot;
}
int deap[MAX];
int fa[MAX][22];
int fuck[MAX][22];
void dfs(int u, int last){
deap[u] = deap[last] + 1;
fa[u][0] = last;
fuck[u][0] = ar[u];
for(int i = 1; (1 << i) <= deap[u]; ++i){
fa[u][i] = fa[fa[u][i - 1]][i - 1];
fuck[u][i] = (fuck[u][i-1]^fuck[fa[u][i-1]][i-1]);
}
for(int i = head[u]; i; i = tr[i].nex){
int v = tr[i].to;
if(v != last)dfs(v, u);
}
}
int lca(int x, int y){
if(deap[x] < deap[y])swap(x, y);
int ans = 0;
for(int i = 20; i >= 0; --i){
if(deap[fa[x][i]] >= deap[y]){
ans ^= fuck[x][i];
x = fa[x][i];
}
}
if(x == y){
ans ^= ar[x];
return ans;
}
for(int i = 20; i >= 0; --i){
if(fa[x][i] != fa[y][i]){
ans ^= fuck[x][i];
ans ^= fuck[y][i];
x = fa[x][i];
y = fa[y][i];
}
}
ans ^= fuck[x][1] ^ fuck[y][1] ^ ar[fa[x][0]];
return ans;
}
void work(){
cin >> n >> m;
for(int i = 1; i <= n; ++i)cin >> ar[i];
for(int i = 1; i < n; ++i){
cin >> a >> b;
add(a, b);
add(b, a);
}
dfs(1, 0);
for(int i = 1; i <= m; ++i){
cin >> a >> b;
cout<<lca(a, b)<<endl;
}
}
int main(){
io;
work();
return 0;
}