#include #define lg2(x) (31 - __builtin_clz(x)) #define ad(x) (((x - 1) ^ 1) + 1) const int N = 100054, M = N * 2, LN = 19; int n, q; int p[N], Max[N], root[N]; namespace ST { struct node {int v, lc, rc;} x[3333333]; int cnt = 0; int merge(int id1, int id2, int L, int R) { if (!(id1 && id2)) return id1 | id2; if (L == R) throw "orzfy"; int M = (L + R - 1) >> 1; x[id1].lc = merge(x[id1].lc, x[id2].lc, L, M); x[id1].rc = merge(x[id1].rc, x[id2].rc, M + 1, R); return x[id1].v = x[id1].lc[x].v + x[id1].rc[x].v, id1; } int adj(int id, int L, int R, int h, int v) { id || (id = ++cnt, x[id].v = x[id].lc = x[id].rc = 0), x[id].v += v; if (L == R) return id; int M = (L + R - 1) >> 1; h <= M ? x[id].lc = adj(x[id].lc, L, M, h, v) : (x[id].rc = adj(x[id].rc, M + 1, R, h, v)); return id; } int range(int id, int L, int R, int ql, int qr) { if (!id || ql > R || L > qr) return 0; if (ql <= L && R <= qr) return x[id].v; int M = (L + R - 1) >> 1, s = 0; if (ql <= M) s += range(x[id].lc, L, M, ql, qr); if (qr > M) s += range(x[id].rc, M + 1, R, ql, qr); return s; } } int ancestor(int x) {return p[x] == x ? x : (p[x] = ancestor(p[x]));} namespace Tree { int E, cur; int p[N], dep[N]; int to[M], first[N], next[M]; int cnt, id[N], st[LN][M], *ord = *st; inline int dmin(const int x, const int y) {return dep[x] < dep[y] ? x : y;} void init() { E = cnt = 0, memset(first, 0, (n + 1) << 2); } inline void addedge(int u, int v) { to[++E] = v, next[E] = first[u], first[u] = E; to[++E] = u, next[E] = first[v], first[v] = E; } void dfs(int x) { int i, y; ord[cnt] = x, id[x] = cnt++; for (i = first[x]; i; i = next[i]) if ((y = to[i]) != p[x]) p[y] = x, dep[y] = dep[x] + 1, dfs(y), ord[cnt++] = x; } void build_st_table() { int *f, *g = ord, i, j, k = cnt; for (j = 0; 1 << j + 1 <= cnt; ++j) { f = g, g = st[j + 1], k -= 1 << j; for (i = 0; i < k; ++i) g[i] = dmin(f[i], f[i + (1 << j)]); } } inline int LCA(int x, int y) { int L = std::min(id[x], id[y]), R = (id[x] ^ id[y] ^ L) + 1, c = lg2(R - L); return dmin(st[c][L], st[c][R - (1 << c)]); } inline int dist(int x, int y) {return dep[x] + dep[y] - dep[LCA(x, y)] * 2;} void udfs(int x) { int i, y; if (x != cur) { // printf("udfs %d -> %d\n", x, cur); ::p[ancestor(x)] = cur, root[cur] = ST::merge(root[cur], root[x], 1, n); } for (i = first[x]; i; i = next[i]) if ((y = to[i]) != p[x]) udfs(y); } void adjust(int x) {udfs(cur = x), first[x] = 0;} } void work() { int i, u, v, U, V, op, ans; scanf("%d", &n), Tree::init(); ST::cnt = 0; for (i = 1; i <= n; ++i) Max[i] = p[i] = i, root[i] = ST::adj(0, 1, n, i, 1); for (i = 1; i < n; ++i) scanf("%d%d", &u, &v), Tree::addedge(u, v); Tree::dfs(1), Tree::build_st_table(); for (scanf("%d", &q); q; --q) if (scanf("%d%d", &op, &u), op == 1) { if (p[u] == u && Tree::first[u]) Tree::adjust(u); } else { scanf("%d", &v), U = ancestor(u), V = ancestor(v); // printf("%d, %d -> %d, %d\n", u, v, U, V); if (U == V) { ans = ST::range(root[U], 1, n, std::min(u, v) + 1, std::max(u, v)); } else { ans = Tree::dist(U, V); ans += ST::range(root[U], 1, n, u + 1, n); ans += ST::range(root[V], 1, n, v + 1, n); } printf("%d\n", ans); } } int main() { int T; for (scanf("%d", &T); T; --T) work(); return 0; }