发现答案在二进制下最多为 (16) 位,那么将 (v) 到 (u) 的路径每 (256) 个点分为一段,得同一段在二进制下 (dis) 的高 (8) 位相同。
设 (f_{x,i}) 为从 (x) 向上的一段,高 (8) 位为 (i) 时答案的最大值,询问就暴力跳即可。
#include<bits/stdc++.h>
#define maxn 100010
#define maxm 310
#define S 255
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,q;
int a[maxn],fa[maxn],dep[maxn],f[maxn][maxm],g[maxn];
struct edge
{
int to,nxt;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to)
{
e[++edge_cnt]={to,head[from]},head[from]=edge_cnt;
}
void dfs(int x,int fath)
{
fa[x]=fath,dep[x]=dep[fath]+1;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(y==fath) continue;
dfs(y,x);
}
}
void work(int x)
{
int p=x;
for(int i=0;i<=S&&p;++i,p=fa[p])
{
int v=a[p]>>8;
f[x][v^S]=max(f[x][v^S],(a[p]^i)|(S<<8));
}
g[x]=p;
for(int j=0;j<8;++j)
for(int i=0;i<=S;++i)
if(f[x][i^(1<<j)])
f[x][i]=max(f[x][i],f[x][i^(1<<j)]^(1<<(j+8)));
}
int main()
{
read(n),read(q);
for(int i=1;i<=n;++i) read(a[i]);
for(int i=1;i<n;++i)
{
int x,y;
read(x),read(y);
add(x,y),add(y,x);
}
dfs(1,0);
for(int i=1;i<=n;++i) work(i);
while(q--)
{
int x,y,p,ans=0;
read(x),read(y),p=y;
for(int i=0;dep[g[p]]>=dep[x]&&p;++i,p=g[p]) ans=max(ans,f[p][i]);
while(dep[p]>=dep[x]) ans=max(ans,a[p]^(dep[y]-dep[p])),p=fa[p];
printf("%d
",ans);
}
return 0;
}