// 2. Gán các đỉnh trên đường đi từ u đến gốc bằng 0
// 3. In ra giá trị của nút u hiện tại
// Ban đầu các nút đều có giá trị = 0
// - Để trả lời được truy vấn loại 3 thì ta cần xác định truy vấn gần nhất tác động lên u là thuộc loại 1 hay loại 2
// - Gọi latest_type1, latest_type2 lần lượt là chỉ số của truy vấn loại 1, loại 2 gần nhất tác động lên u
// nếu không tồn tại thì latest_type1/latest_type2 = -1
// => Nếu latest_type1 > latest_type2 thì giá trị của nút u = 1, ngược lại = 0
// - Để tính latest_type1 và latest_type2 thì ta dùng 2 cây Segment Tree để quản lí mỗi loại truy vấn
// - Đối với truy vấn loại 1 là Update Cây con và Truy vấn 1 đỉnh thì đã quá quen thuộc
// - Riêng đối với truy vấn loại 2 là Update Đường đi và Truy vấn 1 đỉnh thì ta sẽ áp dụng kiến thức liên quan đến prefix sum
// - Với mỗi cây con gốc u ta sẽ cho tương ứng với đoạn [tin(u), tout(u)] trên Euler Tour
// - Do đó khi ta thay đổi giá trị của 1 đỉnh v nào đấy thì giá trị của những đỉnh là tổ tiên của v, hay nói cách khác là những đỉnh nằm trên đường đi từ v đến gốc cũng sẽ bị thay đổi theo.
// - Nên khi update đường đi từ v đến gốc thì đơn giản là ta chỉ cần update tin(v)
// - Còn khi get giá trị của v thì ta get trong đoạn [tin(v), tout(v)]
int n, q;
vector<int> adj[N];
int tin[N], tout[N], timer;
void dfs(int u, int p){
tin[u]=++timer;
for(int v : adj[u]){
if(v == p)continue;
dfs(v, u);
}
tout[u]= timer;
}
struct SegTree {
int n;
vector<int> seg;
vector<int> lazy;
SegTree(int n): n(4* n){
seg.resize(4* n, -1);
lazy.resize(4* n, -1);
}
void push(int id){
if(lazy[id]!=-1){
seg[id *2]= lazy[id *2]= lazy[id];
seg[id *2+1]= lazy[id *2+1]= lazy[id];
lazy[id]=-1;
}
}
void update(int id, int l, int r, int u, int v, int val){
if(l > v || r < u)return;
if(u <= l && r <= v){
seg[id]= val;
lazy[id]= val;
return;
}
push(id);
int mid =(l + r)>>1;
update(id *2, l, mid, u, v, val);
update(id *2+1, mid +1, r, u, v, val);
seg[id]= max(seg[id *2], seg[id *2+1]);
}
int get(int id, int l, int r, int u, int v){
if(l > v || r < u)return-1;
if(u <= l && r <= v)return seg[id];
push(id);
int mid =(l + r)>>1;
return max(get(id *2, l, mid, u, v), get(id *2+1, mid +1, r, u, v));
}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>> n;
for(int i =0; i < n -1; i++){
int u, v;
cin>> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
timer =0;
dfs(1, -1);
cin>> q;
SegTree segtree1(n +1), segtree2(n +1);
for(int i =0; i < q; i++){
int type, u;
cin>> type >> u;
if(type ==1){
segtree1.update(1, 1, n, tin[u], tout[u], i);
}
elseif(type ==2){
segtree2.update(1, 1, n, tin[u], tin[u], i);
}
else{
int latest_type1 = segtree1.get(1, 1, n, tin[u], tin[u]);
int latest_type2 = segtree2.get(1, 1, n, tin[u], tout[u]);