\(\text{Solution}\)
很显然的暴力就是把路径上的数抽出来弄个线性基求答案
再优化一下就是用倍增的方式把数抽出来
倍增时涉及两个线性基合并,然后就是 \(O(3600q\log n)\) 了
竟没想到它可以过
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#define RE register
#define IN inline
using namespace std;
typedef long long LL;
const int N = 20005;
int n, q, fa[N][16], h[N], tot, dep[N];
LL a[N];
struct edge{int to, nxt;}e[N << 1];
IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}
struct node{
LL p[61];
IN node(){for(RE int i = 0; i < 61; i++) p[i] = 0;}
}f[N][16];
IN void Insert(node &a, LL x)
{
for(RE int i = 60; i >= 0; i--)
if ((x >> i) & 1)
{
if (!a.p[i]){a.p[i] = x; return;}
x ^= a.p[i];
}
}
IN void Merge(node &a, node b)
{
for(RE int i = 60; i >= 0; i--)
if (b.p[i]) Insert(a, b.p[i]);
}
void dfs(int x, int dad)
{
for(RE int i = 1; i <= 15; i++)
if (fa[x][i - 1]) fa[x][i] = fa[fa[x][i - 1]][i - 1],
Merge(f[x][i], f[x][i - 1]), Merge(f[x][i], f[fa[x][i - 1]][i - 1]);
else break;
for(RE int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == dad) continue;
Insert(f[v][0], a[v]), fa[v][0] = x, dep[v] = dep[x] + 1;
dfs(v, x);
}
}
IN node Query(int u, int v)
{
node tmp;
if (dep[u] < dep[v]) swap(u, v);
int deep = dep[u] - dep[v];
for(RE int i = 15; i >= 0; i--)
if ((deep >> i) & 1) Merge(tmp, f[u][i]), u = fa[u][i];
if (u == v){Insert(tmp, a[u]); return tmp;}
for(RE int i = 15; i >= 0; i--)
if (fa[u][i] ^ fa[v][i])
Merge(tmp, f[u][i]), Merge(tmp, f[v][i]), u = fa[u][i], v = fa[v][i];
Insert(tmp, a[u]), Insert(tmp, a[v]), Insert(tmp, a[fa[u][0]]);
return tmp;
}
IN void read(int &x)
{
x = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar());
for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
}
IN void readLL(LL &x)
{
x = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar());
for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
}
int main()
{
read(n), read(q);
for(RE int i = 1; i <= n; i++) readLL(a[i]);
for(RE int i = 1, u, v; i < n; i++) read(u), read(v), add(u, v), add(v, u);
dfs(1, 0); node tmp; LL ans;
for(RE int u, v; q; --q)
{
read(u), read(v), tmp = Query(u, v), ans = 0;
for(RE int i = 60; i >= 0; i--) ans = max(ans, ans ^ tmp.p[i]);
printf("%lld\n", ans);
}
}