#pragma comment(linker, "/STACK:102400000,102400000") //#include #include #include #include #include #include #include #include #include #define fi first #define se second #define endl '\n' #define o2(x) (x)*(x) #define BASE_MAX 31 #define mk make_pair #define eb push_back #define SZ(x) ((int)(x).size()) #define all(x) (x).begin(), (x).end() #define clr(a, b) memset((a),(b),sizeof((a))) #define iis std::ios::sync_with_stdio(false); cin.tie(0) #define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end()) using namespace std; #pragma optimize("-O3") typedef long long LL; typedef unsigned long long uLL; typedef pair pii; inline LL read() { LL x = 0;int f = 0; char ch = getchar(); while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x = f ? -x : x; } inline void write(LL x, bool f) { if (x == 0) {putchar('0'); if(f)putchar('\n');else putchar(' ');return;} if (x < 0) {putchar('-');x = -x;} static char s[23]; int l = 0; while (x != 0)s[l++] = x % 10 + 48, x /= 10; while (l)putchar(s[--l]); if(f)putchar('\n');else putchar(' '); } int lowbit(int x) { return x & (-x); } templateT big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; } templateT sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; } templateT big(const T &f, const R &...r) { return big(f, big(r...)); } templateT sml(const T &f, const R &...r) { return sml(f, sml(r...)); } void debug_out() { cerr << '\n'; } templatevoid debug_out(const T &f, const R &...r) {cerr << f << " ";debug_out(r...);} #define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__); const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; const int HMOD[] = {1000000009, 1004535809}; const LL BASE[] = {1572872831, 1971536491}; const int mod = 1e9 + 7;//998244353 const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; const int MXN = 2e5 + 7; const int MXE = 4e5 + 7; int n, m; struct lp { int v, nex; } cw[MXE]; int tot, head[MXN]; int tid[MXN], hid[MXN], inde, rid[MXN]; int up[MXN][20], lg[MXN], DEP[MXN]; void add_edge(int u,int v) { cw[++tot].v = v; cw[tot].nex = head[u]; head[u] = tot; cw[++tot].v = u; cw[tot].nex = head[v]; head[v] = tot; } void dfs(int u, int ba) { DEP[u] = DEP[ba] + 1; tid[u] = ++ inde; rid[inde] = u; for(int i = head[u], v; ~i; i = cw[i].nex) { v = cw[i].v; if(v == ba) continue; up[v][0] = u; dfs(v, u); } hid[u] = inde; } void init() { dfs(1, -1); for (int j = 1; j <= lg[n]; ++j) for (int i = 1; i <= n; ++i) up[i][j] = up[up[i][j - 1]][j - 1]; } int lca(int x, int y) { if (DEP[x] > DEP[y]) swap(x, y); int k = DEP[y] - DEP[x]; for (int i = 0; k; k = k / 2, ++i) if (k & 1) y = up[y][i]; if (x == y) return x; k = DEP[x]; for (int i = lg[k]; i >= 0; --i) if (up[x][i] != up[y][i]) x = up[x][i], y = up[y][i]; return up[x][0]; } int query(int i, int j) { return DEP[i] + DEP[j] - 2 * DEP[lca(i, j)]; } int sum[MXN<<2]; void build(int l, int r, int rt) { sum[rt] = 0; if(l == r) return; int mid = (l + r) >> 1; build(l, mid, rt<<1), build(mid + 1, r, rt<<1|1); } void update(int p, int v, int l, int r, int rt) { if(l == r) { sum[rt] = v; return; } int mid = (l + r) >> 1; if(p <= mid) update(p, v, l, mid, rt<<1); else update(p, v, mid + 1, r, rt<<1|1); sum[rt] = big(sum[rt<<1], sum[rt<<1|1]); } int query(int v, int l, int r, int rt) { if(sum[rt] < v) return -1; if(l == r) { if(l > v) return -1; return l; } int mid = (l + r) >> 1; if(sum[rt<<1] >= v) { return query(v, l, mid, rt<<1); }else { return query(v, mid + 1, r, rt<<1|1); } } struct LP{ int l, r, sum; }qu[MXN*40]; int wnis, Rk[MXN]; void Z_update(int l, int r, int last, int &cur, int x) { qu[++wnis] = qu[last]; qu[wnis].sum = qu[last].sum + 1; cur = wnis; if (l == r) return; int mid = (l + r) >> 1; if (x <= mid)Z_update(l, mid, qu[last].l, qu[cur].l, x); else Z_update(mid + 1, r, qu[last].r, qu[cur].r, x); } int Z_query(int l, int r, int p, int lst, int cur) { if (l == r) return qu[cur].sum - qu[lst].sum; int mid = (l + r) >> 1; if (p <= mid) return Z_query(l, mid, p, qu[lst].l, qu[cur].l); return qu[qu[cur].l].sum - qu[qu[lst].l].sum + Z_query(mid + 1, r, p, qu[lst].r, qu[cur].r); } int main() { for (int i = 2; i <= 200001; ++i) lg[i] = lg[i / 2] + 1; int tim = read(); while(tim --) { n = read(); tot = -1; inde = wnis = 0; Rk[0] = qu[0].l = qu[0].r = qu[0].sum = 0; for(int i = 1; i <= n; ++i) head[i] = -1; for(int i = 1, a ,b; i < n; ++i) { a = read(), b = read(); add_edge(a, b); } init(); assert(inde == n); build(1, n, 1); for(int i = 1; i <= n; ++i) { Z_update(1, n, Rk[i-1], Rk[i], rid[i]); } // for(int i = 1; i <= n; ++i) { // printf("%d ", hid[i]); // } // printf("\n"); // for(int i = 1; i <= n; ++i) { // printf("%d ", tid[i]); // } // printf("\n"); // for(int i = 1; i <= n; ++i) { // printf("%d ", rid[i]); // } // printf("\n"); int Q = read(), opt, x, y; while(Q --) { opt = read(); if(opt == 1) { x = read(); update(tid[x], hid[x], 1, n, 1); }else { x = read(), y = read(); int px = query(tid[x], 1, n, 1); int py = query(tid[y], 1, n, 1); // debug(px, py, tid[x], tid[y], x, y) if(px == -1 && py == -1) { printf("%d\n", query(x, y)); }else if(px == -1) { py = rid[py]; int tmp = query(x, py); int ly = Z_query(1, n, y, Rk[tid[py]-1], Rk[hid[py]]); printf("%d\n", tmp + (hid[py]-tid[py]+1) - ly); }else if(py == -1) { px = rid[px]; int tmp = query(px, y); int lx = Z_query(1, n, x, Rk[tid[px]-1], Rk[hid[px]]); // debug(x, y, tmp, lx, (hid[px]-tid[px]+1)) printf("%d\n", tmp + (hid[px]-tid[px]+1) - lx); }else if(px != py) { px = rid[px], py = rid[py]; int tmp = query(px, py); int lx = Z_query(1, n, x, Rk[tid[px]-1], Rk[hid[px]]); int ly = Z_query(1, n, y, Rk[tid[py]-1], Rk[hid[py]]); printf("%d\n", tmp+(hid[px]-tid[px]+1)-lx+ (hid[py]-tid[py]+1)-ly); }else { px = rid[px], py = rid[py]; int lx = Z_query(1, n, x, Rk[tid[px]-1], Rk[hid[px]]); int ly = Z_query(1, n, y, Rk[tid[py]-1], Rk[hid[py]]); printf("%d\n", abs(lx - ly)); } } } } return 0; }