NamomoCamp Daily 3
代码源oj网址http://oj.daimayuan.top/course/10/problem/451
题解:
主要是要了解异或的一个性质, a x o r b x o r b = a a \ xor\ b \ xor\ b = a a xor b xor b=a,那么在一棵树上,对于两个点 x , y x,y x,y的简单路径唯一,只需要求 x , y x,y x,y分别到根的异或和,异或一遍之再将 x , y x,y x,y的最近公共祖先再异或一遍回来就行。
注意
LCA计算层数的时候用bfs好一点。
代码:
// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int n, T, m;
int fa[N][20];
int pi, p[N], nxt[N * 2], to[N * 2];
int a[N], depth[N];
int s[N];
inline void add_in(int u, int v) {
pi++; nxt[pi] = p[u]; p[u] = pi; to[pi] = v;
}
void bfs()
{
mst(depth, inf);
queue<int> q;
q.push(1);
depth[0] = 0; depth[1] = 1; s[1] = a[1];
while (q.size()) {
int u = q.front(); q.pop();
for (int k = p[u], v = to[k]; k; k = nxt[k], v = to[k]) {
if (depth[v] > depth[u] + 1) {
depth[v] = depth[u] + 1;
s[v] = a[v] ^ s[u];
q.push(v);
fa[v][0] = u;
ffor(i, 1, 19)
fa[v][i] = fa[fa[v][i - 1]][i - 1];
}
}
}
}
void ready()
{
IOS;
cin >> n >> m;
ffor(i, 1, n) cin >> a[i];
ffor(i, 1, n - 1) {
int u, v;
cin >> u >> v;
add_in(u, v);
add_in(v, u);
}
bfs();
}
int LCA(int x, int y)
{
if (depth[x] < depth[y]) swap(x, y);
for (int i = 19; i >= 0; i--) {
int xi = fa[x][i];
if (depth[xi] >= depth[y]) x = xi;
}
if (x == y) return x;
for (int i = 19; i >= 0; i--) {
if (fa[x][i] != fa[y][i]) {
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
void work()
{
int x, y;
cin >> x >> y;
int anc = LCA(x, y), ans = s[x] ^ s[y] ^ a[anc];
cout << ans << '\n';
}
signed main()
{
ready();
while(m--)
work();
return 0;
}