一句话题意:树上两点间路径子集最大异或和。
看了一下线性基发现好强,但我也不太会,先贴代码吧。。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 20005
#define M 200005
#define Mlg 6000005
#define ll long long
using namespace std;
bool ok[N<<1];
int n,m,x,y,q[M][2];
ll a[N],Ans[M];
int son[N],f[N],fa[N],sum,now,p[M],cnt;
int first[N],next[N<<1],to[N<<1],l=1;
int First[N],Next[Mlg],To[Mlg],L;
ll Re()
{
ll x=0;char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x;
}
struct B//linear based
{
ll a[60];
void clr(){memset(a,0,sizeof a);}
void add(ll x)
{
for (int i=59;i>=0;i--)
if (x>>i&1){if (a[i])x^=a[i];else{a[i]=x;break;}}
}
ll ask()
{
ll t=0;
for (int i=59;i>=0;i--) if ((t^a[i])>t) t^=a[i];
return t;
}
}h[N];
void link(int x,int y){to[++l]=y;next[l]=first[x];ok[l]=1;first[x]=l;}
void Link(int x,int y){To[++L]=y;Next[L]=First[x];First[x]=L;}
void Get(int x,int y)
{
son[x]=1;f[x]=0;
for (int i=first[x];i;i=next[i])
if (ok[i]&&to[i]!=y)
{
Get(to[i],x);son[x]+=son[to[i]];
if (son[to[i]]>f[x]) f[x]=son[to[i]];
}
f[x]=max(f[x],sum-son[x]);
if (f[x]<f[now]) now=x;
}
void dfs(int x,int y,int z)
{
fa[x]=z;
h[x]=h[y];
h[x].add(a[x]);
for (int i=first[x];i;i=next[i])
if (ok[i]&&to[i]!=y) dfs(to[i],x,z);
}
void work(int x)
{
if (!First[x]) return;
f[0]=sum=son[x];
Get(x,now=0);
fa[now]=now;
h[now].clr();
h[now].add(a[now]);
for (int i=first[now];i;i=next[i])
if (ok[i]) dfs(to[i],now,to[i]);
cnt=0;
for (int i=First[x];i;i=Next[i])
p[++cnt]=To[i];
First[x]=0;
for (int i=1;i<=cnt;i++)
if (fa[q[p[i]][0]]==fa[q[p[i]][1]])
Link(fa[q[p[i]][0]],p[i]);
else
{
B t=h[q[p[i]][0]];
B*k=h+q[p[i]][1];
for (int j=59;j>=0;j--)
if (k->a[j]) t.add(k->a[j]);
Ans[p[i]]=t.ask();
}
for (int i=first[now];i;i=next[i])
if (ok[i]) ok[i^1]=0,work(to[i]);
}
int main()
{
n=Re(),m=Re();
for (int i=1;i<=n;i++)
a[i]=Re();
for (int i=1;i<n;i++)
x=Re(),y=Re(),link(x,y),link(y,x);
for (int i=1;i<=m;i++)
{
q[i][0]=Re(),q[i][1]=Re();
if (q[i][0]==q[i][1]) Ans[i]=a[q[i][0]];
else Link(1,i);
}
son[1]=n;work(1);
for (int i=1;i<=m;i++)
printf("%lld\n",Ans[i]);
return 0;
}