#include #include #include #include using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; #define lson rt * 2 #define rson rt * 2 + 1 #define MP make_pair const int N = 1e6 + 100; const int M = 20; int n, m, q, dfs_cnt, st_cnt; int dfs_st[N * 2], dfs_ed[N * 2], ST_idx[N * 2], ST[N * 2][M + 1], rev[N * 2], Log[N * 2], lis[N * 2]; ll dis[N], dep[N]; vector > V[N]; void dfs(int u, int fa) { dfs_st[u] = ++dfs_cnt; rev[dfs_cnt] = u; ST[++st_cnt][0] = dfs_cnt; lis[st_cnt] = dfs_cnt; ST_idx[u] = st_cnt; for (int i = 0; i < V[u].size(); i++) { int v = V[u][i].first, c = V[u][i].second; if (v == fa) continue; dis[v] = dis[u] + c; dep[v] = dep[u] + 1; dfs(v, u); ST[++st_cnt][0] = dfs_st[u]; lis[st_cnt] = dfs_st[u]; } dfs_ed[u] = dfs_cnt; } void init() { for (int j = 1; j <= M; j++) { for (int i = 1; i <= st_cnt; i++) { ST[i][j] = min(ST[i][j - 1], ST[min(st_cnt, i + (1 << (j - 1)))][j - 1]); } } int len = 1, cnt = 0; for (int i = 1; i <= st_cnt; i++) { if (len * 2 == i) { len *= 2; cnt++; } Log[i] = cnt; } } int LCA(int a, int b) { a = ST_idx[a], b = ST_idx[b]; if (a > b) swap(a, b); int g = Log[b - a + 1]; return rev[min(ST[a][g], ST[b - (1 << g) + 1][g])]; } ll DIS(int a, int b) { int fa = LCA(a, b); return dis[a] + dis[b] - 2 * dis[fa]; } namespace Tree { int tree[N * 4]; void build(int l, int r, int rt) { tree[rt] = 0; if (l == r) return; int m = (l + r) / 2; build(l, m, lson); build(m + 1, r, rson); } void insert(int rl, int rr, int x, int l, int r, int rt) { if (rl == l && rr == r) return void(tree[rt] = x); int m = (l + r) / 2; if (rr <= m) insert(rl, rr, x, l, m, lson); else if (m < rl) insert(rl, rr, x, m + 1, r, rson); else { insert(rl, m, x, l, m, lson); insert(m + 1, rr, x, m + 1, r, rson); } } int query(int id, int l, int r, int rt) { if (tree[rt] || l == r) return tree[rt]; int m = (l + r) / 2; if (id <= m) return query(id, l, m, lson); else return query(id, m + 1, r, rson); } } int tot, ls[N * 30], rs[N * 30], cnt[N * 30], root[N]; void insert(int ro, int x) { int p = ++tot; root[ro] = tot; int np = root[ro - 1]; int l = 1, r = n, m; while (true) { cnt[p] = cnt[np] + 1; if (l == r) return; int m = (l + r) / 2; if (x <= m) { ls[p] = ++tot; rs[p] = rs[np]; p = ls[p], np = ls[np]; r = m; } else { ls[p] = ls[np]; rs[p] = ++tot; p = rs[p], np = rs[np]; l = m + 1; } } } int query(int id, int l, int r, int np, int p) { if (l == r) return 0; int m = (l + r) / 2; if (id <= m) return query(id, l, m, ls[np], ls[p]) + cnt[rs[p]] - cnt[rs[np]]; else return query(id, m + 1, r, rs[np], rs[p]); } int main() { //freopen("0.txt", "r" ,stdin); int T, a, b, c, q; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i < n; i++) { scanf("%d%d", &a, &b); V[a].push_back(MP(b, 1)); V[b].push_back(MP(a, 1)); } dfs(1, 1); init(); Tree::build(1, n, 1); for (int i = 1; i <= n; i++) insert(i, rev[i]); scanf("%d", &q); while (q--) { scanf("%d", &a); if (a == 1) { scanf("%d", &b); int id = Tree::query(dfs_st[b], 1, n, 1); if (id != 0 && dfs_st[id] <= dfs_st[b]) continue; Tree::insert(dfs_st[b], dfs_ed[b], b, 1, n, 1); } else { scanf("%d%d", &b, &c); int bb = Tree::query(dfs_st[b], 1, n, 1); int cc = Tree::query(dfs_st[c], 1, n, 1); int ans = 0; if (bb && bb == cc) { ans = query(b, 1, n, root[dfs_st[bb] - 1], root[dfs_ed[bb]]); ans -= query(c, 1, n, root[dfs_st[bb] - 1], root[dfs_ed[bb]]); ans = abs(ans); } else { if (bb != 0) ans += query(b, 1, n, root[dfs_st[bb] - 1], root[dfs_ed[bb]]); else bb = b; if (cc != 0) ans += query(c, 1, n, root[dfs_st[cc] - 1], root[dfs_ed[cc]]); else cc = c; ans += DIS(bb, cc); } printf("%d\n", ans); } } tot = dfs_cnt = st_cnt = 0; for (int i = 1; i <= n; i++) V[i].clear(); } return 0; }