#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <queue>
#include <cmath>
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define mem(a,b) memset((a),(b),sizeof(a))
using namespace std;
typedef long long LL;
inline int read_int(){
int t=0;bool sign=false;char c=getchar();
while(!isdigit(c)){sign|=c=='-';c=getchar();}
while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
return sign?-t:t;
}
inline LL read_LL(){
LL t=0;bool sign=false;char c=getchar();
while(!isdigit(c)){sign|=c=='-';c=getchar();}
while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
return sign?-t:t;
}
inline void write(LL x){
register char c[21],len=0;
if(!x)return putchar('0'),void();
if(x<0)x=-x,putchar('-');
while(x)c[++len]=x%10,x/=10;
while(len)putchar(c[len--]+48);
}
inline void space(LL x){write(x),putchar(' ');}
inline void enter(LL x){write(x),putchar('\n');}
const int MAXN=2e4+5,MAXQ=2e5+5,MAXM=63;
struct LinearBase{
LL p[MAXM];
void Clear(){mem(p,0);}
void Insert(LL x){
for(int i=MAXM-1;i>=0;i--){
if((x>>i)&1){
if(p[i])
x^=p[i];
else
return p[i]=x,void();
}
}
}
LL query(){
LL ans=0LL;
for(int i=MAXM-1;i>=0;i--){
if((ans^p[i])>ans)
ans^=p[i];
}
return ans;
}
};
LinearBase Merge(const LinearBase &a,const LinearBase &b){
LinearBase c=a;
_for(i,0,MAXM)
if(b.p[i])
c.Insert(b.p[i]);
return c;
}
struct Edge{
int to,next;
}edge[MAXN<<1];
int head[MAXN],edge_cnt;
void Insert(int u,int v){
edge[++edge_cnt].next=head[u];
edge[edge_cnt].to=v;
head[u]=edge_cnt;
}
int sz[MAXN],mson[MAXN],tot_sz,root,root_sz;
LL a[MAXN],ans[MAXQ];
bool vis[MAXN],mark[MAXN];
LinearBase p[MAXN];
vector<pair<int,int> > q[MAXN];
vector<int> d,sd;
void find_root(int u,int fa){
sz[u]=1;mson[u]=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]||v==fa)
continue;
find_root(v,u);
sz[u]+=sz[v];
mson[u]=max(mson[u],sz[v]);
}
mson[u]=max(mson[u],tot_sz-sz[u]);
if(mson[u]<root_sz){
root=u;
root_sz=mson[u];
}
}
void dfs(int u,int fa){
d.push_back(u);
p[u]=p[fa];
p[u].Insert(a[u]);
_for(i,0,q[u].size()){
if(!mark[q[u][i].first])
continue;
LinearBase t=Merge(p[u],p[q[u][i].first]);
t.Insert(a[root]);
ans[q[u][i].second]=t.query();
}
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]||v==fa)
continue;
dfs(v,u);
}
}
void query(int u){
sd.clear();
mark[u]=true;
p[u].Clear();
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v])
continue;
d.clear();
dfs(v,u);
_for(i,0,d.size()){
mark[d[i]]=true;
sd.push_back(d[i]);
}
}
mark[u]=false;
_for(i,0,sd.size())
mark[sd[i]]=false;
}
void solve(int u){
int cur_sz=tot_sz;
vis[u]=true;query(u);
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v])
continue;
tot_sz=sz[v]>sz[u]?cur_sz-sz[u]:sz[v];root_sz=MAXN;
find_root(v,u);
solve(root);
}
}
int main()
{
int n=read_int(),t=read_int(),u,v;
_for(i,0,n)
a[i]=read_LL();
_for(i,1,n){
u=read_int()-1,v=read_int()-1;
Insert(u,v);
Insert(v,u);
}
_for(i,0,t){
u=read_int()-1,v=read_int()-1;
if(u==v)
ans[i]=a[u];
else{
q[u].push_back(make_pair(v,i));
q[v].push_back(make_pair(u,i));
}
}
root_sz=MAXN;
tot_sz=n;
find_root(0,-1);
solve(root);
_for(i,0,t)
enter(ans[i]);
return 0;
}