#include using namespace std; #include namespace po167{ template struct Sparse_table{ int n; int depth; std::vector> val; void init(std::vector &v){ depth = 1; n = v.size(); while ((1 << depth) <= n) depth++; val.resize(depth); val[0] = v; for (int i = 1; i < depth; i++){ val[i].resize(n); for (int j = 0; j <= n - (1 << i); j++){ val[i][j] = op(val[i - 1][j], val[i - 1][j + (1 << (i - 1))]); } } } Sparse_table(std::vector v){ init(v); } Sparse_table(){} // 0 <= l < r <= n // if l == r : assert T prod(int l, int r){ assert(0 <= l && l < r && r <= n); int z=31-__builtin_clz(r-l); return op(val[z][l], val[z][r - (1 << z)]); } }; } namespace po167{ int op(int a, int b){ return std::min(a, b); } struct LCA{ Sparse_table table; std::vector depth; std::vector E; std::vector order; int var_num; void init(std::vector> &g, int root = 0){ var_num = g.size(); assert(0 <= root && root < var_num); std::vector val; depth.assign(var_num, -1); depth[root] = 0; E.resize(var_num); std::vector tmp; order.clear(); tmp.reserve(var_num); order.reserve(var_num); int c = 0; auto dfs = [&](auto self, int var, int pare) -> void { E[var] = c++; if (var != root) tmp.push_back(E[pare]); order.push_back(var); for (auto x : g[var]) if (depth[x] == -1){ depth[x] = depth[var] + 1; self(self, x, var); } }; dfs(dfs, root, -1); assert(c == var_num); table.init(tmp); } void init(std::vector &pare){ int root = -1; int n = pare.size(); std::vector> g(n); for (int i = 0; i < n; i++){ if (pare[i] < 0){ assert(root == -1); root = i; } else{ assert(0 <= pare[i] && pare[i] < n); g[pare[i]].push_back(i); } } assert(root != -1); init(g, root); } LCA (std::vector> g, int root = 0){ init(g, root); } LCA (std::vector pare){ init(pare); } LCA(){ } int lca(int a, int b){ assert(0 <= std::min(a, b) && std::max(a, b) < var_num); if (a == b) return a; if (E[a] > E[b]) std::swap(a, b); return order[table.prod(E[a], E[b])]; } int dist(int a, int b){ assert(0 <= std::min(a, b) && std::max(a, b) < var_num); return depth[a] + depth[b] - 2 * depth[lca(a, b)]; } int back(int var, int len){ assert(len <= depth[var]); if (len == 0) return var; int l = 0, r = E[var]; while (r - l > 1){ int m = (l + r) / 2; if (depth[var] - depth[order[table.prod(m, E[var])]] < len){ r = m; } else l = m; } return order[table.prod(l, E[var])]; } // a -> b int jump(int a, int b, int len){ int c = lca(a, b); if (len <= depth[a] - depth[c]) return back(a, len); len -= depth[a] - depth[c]; if (len <= depth[b] - depth[c]) return back(b, depth[b] - depth[c] - len); return -1; } }; } po167::LCA lca; struct F{ int l = -1; int r = -1; int ans = 0; }; F op(F l, F r){ if (l.l == -1) return r; if (r.r == -1) return l; l.ans += r.ans; l.ans += lca.dist(l.r, r.l); l.r = r.r; return l; } F e(){ return F{}; } int main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int N; cin >> N; vector> G(N); for (int i = 0; i < N - 1; i++){ int a, b; cin >> a >> b; a--, b--; G[a].push_back(b); G[b].push_back(a); } lca.init(G); vector L(N), R(N); { int tmp = 0; auto dfs = [&](auto self, int var, int par) -> void { L[var] = tmp; tmp++; for (auto x : G[var]) if (x != par){ self(self, x, var); } R[var] = tmp; }; dfs(dfs, 0, -1); } vector p(N); atcoder::segtree seg(N); for (int i = 0; i < N; i++){ cin >> p[i]; if (p[i]){ seg.set(L[i], {i, i, 0}); } } int Q; cin >> Q; while (Q--){ int t; cin >> t; // 変更クエリ if (t == 1){ int var; cin >> var; var--; p[var] ^= 1; if (p[var]){ seg.set(L[var], {var, var, 0}); } else{ seg.set(L[var], e()); } } // 出力クエリ if (t == 2){ int x, y; cin >> x >> y; x--, y--; F tmp; // x == y のとき if (x == y){ tmp = seg.all_prod(); } // y の部分木内に x が存在するとき else if (L[y] < L[x] && L[x] < R[y]){ // x から y へ行き、その 1 つ前の頂点を考える int z = lca.jump(y, x, 1); tmp = op(seg.prod(0, L[z]), seg.prod(R[z], N)); } // そうでないとき else{ tmp = seg.prod(L[y], R[y]); } if (tmp.l == -1){ tmp.ans = -2; } else{ tmp.ans += lca.dist(tmp.l, tmp.r); } cout << 1 + tmp.ans / 2 << "\n"; } } }