#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N = 4e5 + 50, M = 32 * N;
int tr1[M][2], root1[N], tot1, siz[N]; int w[N], n, q, maxn[M], id[N], it[N]; int head[N], ver[N], net[N], idx, cnt, root2[N]; int tr2[M][2], dep[N], fa[N][25], maxd[M], tot2;
void add(int a, int b) { net[idx] = head[a]; ver[idx] = b; head[a] = idx++; }
void insert1(int p, int q, int i, int k) { if (i < 0) { maxn[p] = k;//记录一下最大dfs序 return; } int v = w[it[k]] >> i & 1; if (q) tr1[p][!v] = tr1[q][!v]; tr1[p][v] = ++tot1; insert1(tr1[p][v], tr1[q][v], i - 1, k); maxn[p] = max(maxn[tr1[p][0]], maxn[tr1[p][1]]); return; }
void insert2(int p, int q, int i, int k) { if (i < 0) { maxd[p] = dep[k];//记录一下最大深度 return; } int v = w[k] >> i & 1; if (q) tr2[p][!v] = tr2[q][!v]; tr2[p][v] = ++tot2; insert2(tr2[p][v], tr2[q][v], i - 1, k); maxd[p] = max(maxd[tr2[p][0]], maxd[tr2[p][1]]); return; }
int query1(int p, int v, int l) { for (int i = 30; ~i; --i) { int s = v >> i & 1; if (maxn[tr1[p][!s]] >= l) p = tr1[p][!s]; else p = tr1[p][s]; } return v ^ w[it[maxn[p]]]; }
int query2(int p, int v, int l) { int res = 0; for (int i = 30; ~i; --i) { int s = v >> i & 1; if (maxd[tr2[p][!s]] >= l) p = tr2[p][!s], res += 1 << i; else p = tr2[p][s]; } return res; }
void dfs(int u, int f) { id[u] = ++cnt, it[cnt] = u; siz[u] = 1, dep[u] = dep[f] + 1, fa[u][0] = f; for (int i = 1; i <= 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; root2[u] = ++tot2; insert2(root2[u], root2[f], 30, u);//按照到根节点的路径建树 for (int i = head[u]; ~i; i = net[i]) { int v = ver[i]; if (v == f) continue; dfs(v, u); siz[u] += siz[v]; } }
int lca(int x, int y) { if (dep[x] > dep[y]) swap(x, y); for (int i = 20; ~i; --i) if (dep[fa[y][i]] >= dep[x]) y = fa[y][i]; if (x == y) return x; for (int i = 20; ~i; --i) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return fa[x][0]; }
int main() { memset(head, -1, sizeof(head)); scanf("%d%d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", &w[i]); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v), add(v, u); } dfs(1, 0); for (int i = 1; i <= n; i++) { root1[i] = ++tot1; insert1(root1[i], root1[i - 1], 30, i); } while (q--) { int op, x, y, z; scanf("%d", &op); if (op == 1) { scanf("%d%d", &x, &z); printf("%d\n", query1(root1[id[x] + siz[x] - 1], z, id[x]));//查找x的子树, } else { scanf("%d%d%d", &x, &y, &z); int u = lca(x, y); printf("%d\n", max(query2(root2[x], z, dep[u]), query2(root2[y], z, dep[u]))); } } return 0; }
|