首先第一眼是一个倍增套线性基,但是$O(Qlog^2Vlog^N)=10^{10}$的复杂度...
即使是st表也只是变成了$O(Nlog^2Vlog^N)$啊
考虑点分治,相对于倍增显著减少了线性基合并(一个往另一个里暴力插)这一O(log^2V)的过程
就是在分治到一个询问的两端点分立于两个子树的时候,合并它们的线性基来统计答案
#include<bits/stdc++.h>
#define CLR(a,x) memset(a,x,sizeof(a))
#define MP make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pa;
const int maxn=2e4+,maxq=2e5+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Node{
int b,i;
};
int N,Q,siz[maxn];
vector<Node> q[maxn];
int eg[maxn*][],egh[maxn],ect;
bool flag[maxn];
ll base[maxn][],tmp[],val[maxn],ans[maxq];
int son[maxn],sct,bel[maxn]; inline void adeg(int a,int b){
eg[++ect][]=b,eg[ect][]=egh[a],egh[a]=ect;
}
inline void getroot(int x,int f,int ssiz,int &rt,int &sm){
siz[x]=;int m=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f||flag[b]) continue;
getroot(b,x,ssiz,rt,sm);
m=max(siz[b],m);siz[x]+=siz[b];
}m=max(ssiz-siz[x],m);
if(m<sm) rt=x,sm=m;
} inline void update(ll *bs,ll v){
for(int i=;i>=;i--){
if(v&(1ll<<i)){
if(!bs[i]){bs[i]=v;break;}
else v^=bs[i];
}
}
} inline ll query(ll *bs,ll v){
for(int i=;i>=;i--){
if((v^bs[i])>v) v^=bs[i];
}return v;
} inline void getbase(int x,int f){
update(base[x],val[x]);
son[++sct]=x;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f||flag[b]) continue;
memcpy(base[b],base[x],sizeof(base[x]));
getbase(b,x);
}
} inline void solve(int x,int ssiz){
flag[x]=;bel[x]=x;CLR(base[x],);
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(flag[b]) continue;
CLR(base[b],);sct=;
getbase(b,);
for(int i=;i<=sct;i++){
int y=son[i];
for(int j=;j<q[y].size();j++){
int b=q[y][j].b;
if(bel[b]!=x) continue;
memcpy(tmp,base[y],sizeof(tmp));
for(int k=;k<=;k++){
if(base[b][k]) update(tmp,base[b][k]);
}
ans[q[y][j].i]=max(query(tmp,),query(tmp,val[x]));
}
}
for(int i=;i<=sct;i++) bel[son[i]]=x;
}
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(flag[b]) continue;
int rt,sm=1e9;
getroot(b,,siz[b]>siz[x]?ssiz-siz[x]:siz[b],rt,sm);
solve(rt,siz[b]>siz[x]?ssiz-siz[x]:siz[b]);
}
} int main(){
int i,j,k;
N=rd(),Q=rd();
for(i=;i<=N;i++) val[i]=rd();
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}
for(i=;i<=Q;i++){
int a=rd(),b=rd();
if(a==b) ans[i]=val[a];
else{
q[a].push_back((Node){b,i});
q[b].push_back((Node){a,i});
} }
int rt,sm=1e9;
getroot(,,N,rt,sm);
solve(rt,N);
for(i=;i<=Q;i++)
printf("%lld\n",ans[i]);
return ;
}