A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中可以保留的最大幸运值是多少。
第一行包含 2 个正整数 n ,q,分别表示城市的数量和旅行者数量。第二行包含 n 个非负整数,其中第 i 个整数 Gi 表示 i 号城市的幸运值。随后 n-1 行,每行包含两个正整数 x ,y,表示 x 号城市和 y 号城市之间有一条道路相连。随后 q 行,每行包含两个正整数 x ,y,表示这名旅行者的旅行计划是从 x 号城市到 y 号城市。N<=20000,Q<=200000,Gi<=2^60
输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。
然后查询的时候正常的查询就好了.
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstring>
using namespace std;
long long read()
{
long long x=0,f=1; char ch=getchar();
while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
return x*f;
}
#define maxn 20010
int n,q; long long val[maxn];
struct EdgeNode{int next,to;}edge[maxn<<1];
int head[maxn],cnt;
void add(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void insert(int u,int v) {add(u,v); add(v,u);}
//==============================================================================================
int size[maxn],deep[maxn],fa[maxn],son[maxn],pl[maxn],sz,pr[maxn],top[maxn],father[maxn][17];long long pre[maxn];
void dfs_1(int now)
{
size[now]=1;
for (int i=1; i<=16; i++)
if (deep[now]>=(1<<i))
father[now][i]=father[father[now][i-1]][i-1];
else break;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now])
{
deep[edge[i].to]=deep[now]+1;
fa[edge[i].to]=now; father[edge[i].to][0]=now;
dfs_1(edge[i].to);
if (size[edge[i].to]>size[son[now]]) son[now]=edge[i].to;
size[now]+=size[edge[i].to];
}
}
void dfs_2(int now,int chain)
{
pl[now]=++sz; pre[sz]=val[now]; top[now]=chain;
if (son[now]) dfs_2(son[now],chain);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now] && edge[i].to!=son[now])
dfs_2(edge[i].to,edge[i].to);
pr[now]=sz;
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=0; i<=16; i++)
if (dd&(1<<i)) x=father[x][i];
for (int i=16; i>=0; i--)
if (father[x][i]!=father[y][i])
x=father[x][i],y=father[y][i];
if (x==y) return x; else return father[x][0];
}
//==============================================================================================
struct XXJ{long long a[61];}Ans;
struct TreeNode{int l,r;XXJ X;}tree[maxn<<2];
void Merge(XXJ &x,XXJ &y,XXJ &z)
{
XXJ tmp;
for (int i=60; i>=0; i--) tmp.a[i]=y.a[i];
for (int i=60; i>=0; i--)
if (z.a[i])
{
long long tp=z.a[i];
for (int i=60; i>=0; i--)
if (tp&(1LL<<i))
if (!tmp.a[i]) {tmp.a[i]=tp; break;}
else tp^=tmp.a[i];
}
for (int i=60; i>=0; i--) x.a[i]=tmp.a[i];
}
void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r;
if (l==r)
{
memset(tree[now].X.a,0LL,sizeof(tree[now].X.a));
long long tp=pre[l];
for (int i=60; i>=0; i--)
if (tp&(1LL<<i))
if (!tree[now].X.a[i]) {tree[now].X.a[i]=tp; break;}
else tp^=tree[now].X.a[i];
return;
}
int mid=(l+r)>>1;
BuildTree(now<<1,l,mid); BuildTree(now<<1|1,mid+1,r);
Merge(tree[now].X,tree[now<<1].X,tree[now<<1|1].X);
}
void Query(int now,int L,int R)
{
if (L<=tree[now].l && R>=tree[now].r) {Merge(Ans,Ans,tree[now].X); return;}
int mid=(tree[now].l+tree[now].r)>>1;
if (L<=mid) Query(now<<1,L,R);
if (R>mid) Query(now<<1|1,L,R);
}
//==============================================================================================
void Solve_Query(int x,int y)
{
int z=LCA(x,y);
if (deep[x]<deep[y]) swap(x,y);
while (deep[top[x]]>deep[z])
Query(1,pl[top[x]],pl[x]),x=fa[top[x]];
Query(1,pl[z],pl[x]);
if (y!=z)
{
int dd=deep[y]-deep[z]-1; z=y;
for (int i=0; i<=16; i++)
if (dd&(1<<i)) z=father[z][i];
if (dd==0) z=y;
while (deep[top[y]]>deep[z])
Query(1,pl[top[y]],pl[y]),y=fa[top[y]];
Query(1,pl[z],pl[y]);
}
}
//==============================================================================================
int main()
{
n=read();q=read();
for (int i=1; i<=n; i++) val[i]=read();
for (int u,v,i=1; i<=n-1; i++) u=read(),v=read(),insert(u,v);
dfs_1(1); dfs_2(1,1); BuildTree(1,1,n);
while (q--)
{
int x=read(),y=read(); long long ans=0;
memset(Ans.a,0LL,sizeof(Ans.a));
Solve_Query(x,y);
for (int i=60; i>=0; i--) if ((ans^Ans.a[i])>ans) ans^=Ans.a[i];
printf("%lld\n",ans);
}
return 0;
}