学习了一下线性基这个东西
log时间支持加法
树链剖分维护一下
再利用线性基查询最大值即可
线性基博文推荐:http://www.cnblogs.com/ljh2000-jump/p/5869991.html
/**************************************************************
Problem: 4568
User: di4CoveRy
Language: C++
Result: Accepted
Time:38544 ms
Memory:185392 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#define LOG 17
#define N 20050
using namespace std;
typedef long long LL;
int Jump[N][LOG+1],D[N],n,q;
LL F[N][LOG+1][64],a[N],ret[64];
bool vis[N];
vector<int> e[N];
inline void merge(LL *B,LL p) {
for (int _=63;_>=0;_--) if (p>>_) {
if (B[_]) p ^= B[_]; else return B[_] = p,(void)0;
}
}
inline void _merge(LL *A,LL *B) {
for (int _=0;_<=63;_++) if (B[_]) merge(A,B[_]);
}
void dfs(int u) {
vis[u] = 1;
for (int i=0;i<(int)e[u].size();i++) {
int v = e[u][i]; if (vis[v]) continue;
D[v] = D[u] + 1;
Jump[v][0] = u;
if (a[u]) F[v][0][63-__builtin_clz(a[u])] = a[u];
dfs(v);
}
}
void _pre() {
for (int i=1;i<=LOG;i++)
for (int _=1;_<=n;_++) {
int tmp = Jump[_][i-1];
Jump[_][i] = Jump[tmp][i-1];
_merge( F[_][i] , F[_][i-1] );
_merge( F[_][i] , F[tmp][i-1] );
}
}
void LCA(int u,int v) {
merge(ret,a[u]) , merge(ret,a[v]);
if (D[u] < D[v]) swap(u,v);
for (int i=LOG;i>=0;i--) if (D[ Jump[u][i] ] >= D[v])
_merge(ret,F[u][i]) , u = Jump[u][i];
if (u == v) return ;
for (int i=LOG;i>=0;i--) if (Jump[u][i] != Jump[v][i])
_merge(ret,F[u][i]) , u = Jump[u][i],
_merge(ret,F[v][i]) , v = Jump[v][i];
_merge(ret,F[u][0]);
}
int main() {
scanf("%d%d",&n,&q);
for (int _=1;_<=n;_++) scanf("%lld",&a[_]);
for (int _=1;_<=n-1;_++) {
int u,v; scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
D[1]=1; dfs(1); _pre();
while (q--) {
memset(ret,0,sizeof(ret));
int u,v; scanf("%d%d",&u,&v);
LCA(u,v);
LL ans = 0;
for (int _=63;_>=0;_--) if ((ans^ret[_]) > ans) ans ^= ret[_];
printf("%lld\n",ans);
}
return 0;
}