#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
const int M = 16;
const int L = 6;
const int Q = 150010;
int n, a[N], q, depth[N], needed;
vector<int> g[N], arr;
vector<pair<int, int> > qu[N];
int nxt[N * (L + 1)][2], mxDepth[N * (L + 1)];
int nodeCnt = 0, newNode, tmpStart;
int ans[Q], mxVal[N];
int canUse[N * (L + 1)], canUseSz = 0;
int underMe[N * (L + 1)];
inline void add(int node, int val, int depth) {
  mxDepth[node] = max(mxDepth[node], depth);
  tmpStart = node;
  for (int b, i = L - 1; i >= 0; i--) {
    b = (((val >> i) & 1));
    if (nxt[node][b] == -1) {
      if (canUseSz != 0)
        newNode = canUse[--canUseSz];
      else
        newNode = nodeCnt++;
      underMe[newNode] = underMe[tmpStart];
      underMe[tmpStart] = newNode;
      nxt[newNode][0] = nxt[newNode][1] = -1;
      mxDepth[newNode] = -1000000010;
      nxt[node][b] = newNode;
    }
    node = nxt[node][b];
    mxDepth[node] = max(mxDepth[node], depth);
  }
}
int b, ret = 0;
inline int getMax(int node, int val, int mnDepth) {
  int ret = 0;
  if (mxDepth[node] < mnDepth) return ret;
  for (int b, i = L - 1; i >= 0; i--) {
    b = (((val >> i) & 1) ^ 1);
    if (nxt[node][b] == -1 || mxDepth[nxt[node][b]] < mnDepth)
      b ^= 1;
    else
      ret ^= (1 << i);
    node = nxt[node][b];
  }
  return ret;
}
int root[N], val[N];
void DFS(int node, int prnt, int d) {
  depth[node] = d;
  int last = -1, lastRoot = -1;
  for (int i = (int)arr.size() - (1 << L); i >= 0; i -= (1 << L)) {
    if (root[arr[i]] == lastRoot) continue;
    lastRoot = root[arr[i]];
    last = lastRoot;
    while (last != -1) {
      canUse[canUseSz++] = last;
      last = underMe[last];
    }
  }
  arr.push_back(node);
  last = lastRoot = -1;
  for (int i = (int)arr.size() - 1; i >= 0; i -= (1 << L)) {
    val[arr[i]] = ((d - depth[arr[i]]) & needed) ^ a[arr[i]];
    if (lastRoot == -1 || (val[arr[i]] & needed) > last) {
      if (canUseSz)
        root[arr[i]] = canUse[--canUseSz];
      else
        root[arr[i]] = nodeCnt++;
      underMe[root[arr[i]]] = -1;
      mxDepth[root[arr[i]]] = -1000000010;
      nxt[root[arr[i]]][0] = nxt[root[arr[i]]][1] = -1;
      last = (val[arr[i]] & needed);
    } else {
      root[arr[i]] = lastRoot;
    }
    mxVal[arr[i]] = last;
    lastRoot = root[arr[i]];
    if ((val[arr[i]] & needed) == last) {
      add(root[arr[i]], val[arr[i]], depth[arr[i]]);
    }
  }
  for (int i = 0; i < (int)g[node].size(); i++) {
    if (g[node][i] == prnt) continue;
    DFS(g[node][i], node, d + 1);
  }
  for (int mxAll, i = 0; i < (int)qu[node].size(); i++) {
    mxAll = 0;
    for (int k, st = d % (1 << L), j = 0; j < (1 << L); j++) {
      k = (depth[qu[node][i].first] - st + (1 << L) - 1) / (1 << L);
      k = st + (1 << L) * k;
      if (k < (int)arr.size()) mxAll = max(mxAll, mxVal[arr[k]]);
      st--;
      if (st == -1) st = (1 << L) - 1;
    }
    for (int k, st = d % (1 << L), j = 0; j < (1 << L); j++) {
      k = (depth[qu[node][i].first] - st + (1 << L) - 1) / (1 << L);
      k = st + (1 << L) * k;
      if (k < (int)arr.size() && mxVal[arr[k]] == mxAll)
        ans[qu[node][i].second] =
            max(ans[qu[node][i].second],
                mxAll ^ getMax(root[arr[k]], j, depth[qu[node][i].first]));
      st--;
      if (st == -1) st = (1 << L) - 1;
    }
  }
  lastRoot = -1;
  for (int i = (int)arr.size() - 1; i >= 0; i -= (1 << L)) {
    if (root[arr[i]] == lastRoot) continue;
    lastRoot = root[arr[i]];
    last = lastRoot;
    while (last != -1) {
      canUse[canUseSz++] = last;
      last = underMe[last];
    }
  }
  last = lastRoot = -1;
  arr.pop_back();
  for (int i = (int)arr.size() - (1 << L); i >= 0; i -= (1 << L)) {
    val[arr[i]] = ((d - depth[arr[i]] - 1) & needed) ^ a[arr[i]];
    if (lastRoot == -1 || (val[arr[i]] & needed) > last) {
      if (canUseSz)
        root[arr[i]] = canUse[--canUseSz];
      else
        root[arr[i]] = nodeCnt++;
      underMe[root[arr[i]]] = -1;
      mxDepth[root[arr[i]]] = -1000000010;
      nxt[root[arr[i]]][0] = nxt[root[arr[i]]][1] = -1;
      last = (val[arr[i]] & needed);
    } else {
      root[arr[i]] = lastRoot;
    }
    mxVal[arr[i]] = last;
    lastRoot = root[arr[i]];
    if ((val[arr[i]] & needed) == last) {
      add(root[arr[i]], val[arr[i]], depth[arr[i]]);
    }
  }
}
int main() {
  needed = ((1 << M) - 1) ^ ((1 << L) - 1);
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
  }
  for (int u, v, i = 0; i < n - 1; i++) {
    scanf("%d%d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u);
  }
  for (int u, v, i = 0; i < q; i++) {
    scanf("%d%d", &u, &v);
    qu[v].push_back(make_pair(u, i));
  }
  DFS(1, -1, 0);
  for (int i = 0; i < q; i++) {
    printf("%d\n", ans[i]);
  }
  return 0;
}
