可以合并的东西都是人类互相伤害的武器……
参照COGS上采矿那道题
可以用树剖维护线性基,复杂度Q(logn)^2(logw)^2
显然会T。。。。
考虑到没有修改
用点分治离线来做
一个询问如果经过当前分治根,则立即处理并不再下传,否则下传到相应子树去做
复杂度nlognlogw+qlogwlogw
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
const int N=20000+5;
const int M=200000+5;
struct linear_base{
ll base[62];
void clr(){mmt(base,0);}
void ins(ll x){
per(i,60,0)
if((x>>i)&1)
if(!base[i]){base[i]=x;break;}
else x^=base[i];
}
ll solve(){
ll ans=0;
per(i,60,0)if((ans^base[i])>ans)ans^=base[i];
return ans;
}
ll operator + (linear_base &b){
static linear_base c;c=b;
per(i,60,0)c.ins(base[i]);
return c.solve();
}
}b[N];
struct Edge{int to,next;}e[N<<1];
int head[N],cnt;
void ins(int u,int v){e[++cnt]=(Edge){v,head[u]};head[u]=cnt;}
void insert(int u,int v){ins(u,v);ins(v,u);}
bool del[N];
int getsize(int u,int fa){
int sz=1;
tra(i,u)
if(e[i].to!=fa&&!del[e[i].to])
sz+=getsize(e[i].to,u);
return sz;
}
int findroot(int u,int fa,int &root,int size){
int sz=1;bool flag=true;
tra(i,u){
int v=e[i].to;if(v==fa||del[v])continue;
int tmp=findroot(v,u,root,size);
flag&=(tmp<<1)<=size;
sz+=tmp;
}
flag&=((size-sz)<<1)<=size;
if(flag)root=u;
return sz;
}
ll g[N];
void dfs(int u,int fa){
b[u].ins(g[u]);
tra(i,u){
int v=e[i].to;if(v==fa||del[v])continue;
b[v]=b[u];
dfs(v,u);
}
}
int bel[N];
void dfs(int u,int fa,int root){
bel[u]=root;
tra(i,u)
if(e[i].to!=fa&&!del[e[i].to])
dfs(e[i].to,u,root);
}
ll ans[M];
struct Query{
int u,v,id;
};
vector<Query>f[N];
void daq(int u){
if(!(int)f[u].size())return;
int size=getsize(u,-1),root;
findroot(u,-1,root,size);
b[root].clr();dfs(root,-1);
del[root]=true;
tra(i,root)
if(!del[e[i].to])
dfs(e[i].to,root,e[i].to);
vector<Query>t=f[u];f[u].clear();
per(i,(int)t.size()-1,0)
if(t[i].u==root||t[i].v==root||bel[t[i].u]!=bel[t[i].v])
ans[t[i].id]=b[t[i].u]+b[t[i].v];
else f[bel[t[i].u]].push_back(t[i]);
tra(i,root)
if(!del[e[i].to])daq(e[i].to);
}
int main(){
int n,m;scanf("%d%d",&n,&m);
rep(i,1,n)scanf("%lld",&g[i]);
rep(i,2,n){int u,v;scanf("%d%d",&u,&v);insert(u,v);}
rep(i,1,m){int u,v;scanf("%d%d",&u,&v);f[1].push_back((Query){u,v,i});}
daq(1);
rep(i,1,m)printf("%lld\n",ans[i]);
return 0;
}