#include <stdio.h> #include <vector> #include <set> #include <string.h> #include <algorithm> #include <assert.h> using namespace std; #define MAXN 131072 int color[MAXN]; int hNext[MAXN], iNode[MAXN], aPos[MAXN]; int used[MAXN], nodesize = 0; struct Node { int p, pPos, dep; vector<int> A; vector<int> seg[10]; void init() { A.clear(); p = -1, dep = 0; } } nodes[262144]; struct Tree { vector<int> g[MAXN]; int root; void init(int n) { for (int i = 0; i < n; i++) g[i].clear(); root = 0; } void addEdge(int x, int y) { g[x].push_back(y); g[y].push_back(x); } } tree; int getSTsize(int n) { int ret = 1; for (ret = 1; ret < n; ret <<= 1); return ret<<1; } int prepare(int u, int p) { int sz = 1, mx = -1, hedge = -1; int v, t; for (int i = 0; i < tree.g[u].size(); i++) { v = tree.g[u][i], t; if (v == p) continue; sz += (t = prepare(v, u)); if (mx < t) mx = t, hedge = v; } hNext[u] = hedge; return sz; } void buildST(Node &nd, int k, int l, int r) { if (l > r) return ; if (l == r) { nd.seg[color[nd.A[l]]][k] = 1; return; } int mid = (l + r)/2; buildST(nd, k<<1, l, mid); buildST(nd, k<<1|1, mid+1, r); for (int i = 0; i < 10; i++) nd.seg[i][k] = nd.seg[i][k<<1] + nd.seg[i][k<<1|1]; } void build(int u, int p) { if (used[u] == 0) { Node &nd = nodes[++nodesize]; nd.init(); for (int i = u; i != -1; i = hNext[i]) { used[i] = 1; iNode[i] = nodesize, aPos[i] = nd.A.size(); nd.A.push_back(i); } for (int i = 0; i < 10; i++) nd.seg[i].clear(), nd.seg[i].resize(getSTsize(nd.A.size()), 0); buildST(nd, 1, 0, nd.A.size() - 1); if (p != -1) { nd.p = iNode[p], nd.pPos = aPos[p]; nd.dep = nodes[nd.p].dep + 1; } } int v; for (int i = 0; i < tree.g[u].size(); i++) { v = tree.g[u][i]; if (v == p) continue; build(v, u); } } int colorsum[10]; void queryST(Node &nd, int k, int l, int r, int x, int y) { if (x <= l && r <= y) { for (int i = 0; i < 10; i++) colorsum[i] += nd.seg[i][k]; return ; } int mid = (l + r)/2; if (x <= mid) queryST(nd, k<<1, l, mid, x, y); if (mid < y) queryST(nd, k<<1|1, mid+1, r, x, y); } void search(int u, int v) { memset(colorsum, 0, sizeof(colorsum)); int x = iNode[u], y = iNode[v]; u = aPos[u], v = aPos[v]; while (x != y) { if (nodes[x].dep < nodes[y].dep) swap(x, y), swap(u, v); assert(u <= nodes[x].A.size()); queryST(nodes[x], 1, 0, nodes[x].A.size() - 1, 0, u); u = nodes[x].pPos, x = nodes[x].p; } if (u > v) swap(u, v); queryST(nodes[x], 1, 0, nodes[x].A.size() - 1, u, v); int ret = 0; for (int i = 0; i < 10; i++) ret = max(ret, colorsum[i]); printf("%d\n", ret); } void modifyST(Node &nd, int k, int l, int r, int x, int v) { if (l == r) { for (int i = 0; i < 10; i++) nd.seg[i][k] = 0; nd.seg[v][k]++; return ; } int mid = (l + r)/2; if (x <= mid) modifyST(nd, k<<1, l, mid, x, v); else modifyST(nd, k<<1|1, mid+1, r, x, v); for (int i = 0; i < 10; i++) nd.seg[i][k] = nd.seg[i][k<<1] + nd.seg[i][k<<1|1]; } void modify(int u, int color) { int x = iNode[u]; modifyST(nodes[x], 1, 0, nodes[x].A.size() - 1, aPos[u], color); } int main() { int testcase; int n, q, x, y; scanf("%d", &testcase); while (testcase--) { scanf("%d %d", &n, &q); for (int i = 0; i < n; i++) scanf("%d", &color[i]), color[i]--; tree.init(n); for (int i = 1; i < n; i++) { scanf("%d %d", &x, &y); x--, y--; tree.addEdge(x, y); } prepare(tree.root = 0, -1); memset(used, 0, sizeof(used)); nodesize = 0; build(tree.root = 0, -1); int cmd, u, v; for (int i = 0; i < q; i++) { scanf("%d %d %d", &cmd, &u, &v); if (cmd == 0) { u--, v--; modify(u, v); } else { u--, v--; search(u, v); } } } return 0; }
|