import sys sys.setrecursionlimit(1_000_000) # ------------------------------------------------------------ # LCA (binary lifting) + Euler tour (iterative) # ------------------------------------------------------------ def solve(): input = sys.stdin.buffer.readline N = int(input()) g = [[] for _ in range(N + 1)] for _ in range(N - 1): a, b = map(int, input().split()) g[a].append(b) g[b].append(a) color = [0] + list(map(int, input().split())) LOG = (N).bit_length() parent = [0] * (N + 1) depth = [0] * (N + 1) tin = [0] * (N + 1) tout = [0] * (N + 1) euler = [0] * N up = [[0] * (N + 1) for _ in range(LOG)] # iterative DFS for tin/tout and parent/depth it = [0] * (N + 1) st = [1] parent[1] = 0 depth[1] = 0 timer = 0 while st: v = st[-1] if it[v] == 0: tin[v] = timer euler[timer] = v timer += 1 if it[v] < len(g[v]): to = g[v][it[v]] it[v] += 1 if to == parent[v]: continue parent[to] = v depth[to] = depth[v] + 1 st.append(to) else: tout[v] = timer - 1 st.pop() for v in range(1, N + 1): up[0][v] = parent[v] for j in range(1, LOG): uj = up[j] ujm1 = up[j - 1] for v in range(1, N + 1): mid = ujm1[v] uj[v] = ujm1[mid] if mid else 0 def is_ancestor(a: int, b: int) -> bool: return tin[a] <= tin[b] and tout[b] <= tout[a] def jump_up(v: int, k: int) -> int: j = 0 while k: if k & 1: v = up[j][v] k >>= 1 j += 1 return v def lca(a: int, b: int) -> int: if is_ancestor(a, b): return a if is_ancestor(b, a): return b v = a for j in range(LOG - 1, -1, -1): nv = up[j][v] if nv and not is_ancestor(nv, b): v = nv return up[0][v] def dist(a: int, b: int) -> int: c = lca(a, b) return depth[a] + depth[b] - 2 * depth[c] # ------------------------------------------------------------ # Segment Tree for "active nodes in Euler order" # Keep: cnt, first, last, sum(dist consecutive) # ------------------------------------------------------------ class Agg: __slots__ = ("cnt", "first", "last", "sum") def __init__(self, cnt=0, first=-1, last=-1, s=0): self.cnt = cnt self.first = first self.last = last self.sum = s def merge(L: Agg, R: Agg) -> Agg: if L.cnt == 0: return R if R.cnt == 0: return L return Agg( L.cnt + R.cnt, L.first, R.last, L.sum + R.sum + dist(L.last, R.first) ) size = 1 while size < N: size <<= 1 seg = [Agg() for _ in range(2 * size)] # build leaves for i in range(N): v = euler[i] if color[v] == 1: seg[size + i] = Agg(1, v, v, 0) for i in range(size - 1, 0, -1): seg[i] = merge(seg[i << 1], seg[i << 1 | 1]) def update(pos: int, v_or_minus1: int): i = size + pos if v_or_minus1 == -1: seg[i] = Agg() else: v = v_or_minus1 seg[i] = Agg(1, v, v, 0) i >>= 1 while i: seg[i] = merge(seg[i << 1], seg[i << 1 | 1]) i >>= 1 def query(l: int, r: int) -> Agg: # [l, r) left = Agg() right = Agg() l += size r += size while l < r: if l & 1: left = merge(left, seg[l]) l += 1 if r & 1: r -= 1 right = merge(seg[r], right) l >>= 1 r >>= 1 return merge(left, right) def steiner_vertices(agg: Agg) -> int: if agg.cnt == 0: return 0 if agg.cnt == 1: return 1 cycle = agg.sum + dist(agg.last, agg.first) edges = cycle // 2 return edges + 1 def query_subtree(u: int) -> int: l = tin[u] r = tout[u] + 1 return steiner_vertices(query(l, r)) def query_complement_subtree(u: int) -> int: l = tin[u] r = tout[u] + 1 left = query(0, l) right = query(r, N) return steiner_vertices(merge(left, right)) # ------------------------------------------------------------ # Process Queries # ------------------------------------------------------------ Q = int(input()) out = [] for _ in range(Q): parts = input().split() t = int(parts[0]) if t == 1: v = int(parts[1]) color[v] ^= 1 if color[v] == 1: update(tin[v], v) else: update(tin[v], -1) else: x = int(parts[1]) y = int(parts[2]) if x == y: out.append(str(steiner_vertices(query(0, N)))) continue if is_ancestor(y, x): # z = child of y on path to x z = jump_up(x, depth[x] - depth[y] - 1) out.append(str(query_complement_subtree(z))) else: # S = subtree(y) out.append(str(query_subtree(y))) sys.stdout.write("\n".join(out)) if __name__ == "__main__": solve()