Bichrome Tree Connectivity

Given a tree.

Initially, all vertices are white.

Inverting the color of the white vertices makes it black, and inverting the color of the black vertices makes it white.

Handle two types of queries.

The first type of query inverts the color of vertex v.

The second type of query answers the number of vertices that can be reached from the white vertices v using only the white vertices and the edges connecting them.

input


N Q
a_1 b_1
a_2 b_2
::
a_ {n-1} b_ {n-1}
t_1 v_1
t_2 v_2
::
t_q v_q


When t_i is 1, it means that it is the first type of query, and when it is 2, it means that it is the second type of query.

output


ans_1
ans_2
::
ans_k


Output the answers to the second type of query in order.

Constraint

* 1 \ leq N, Q \ leq 10 ^ 5
* 1 \ leq a_i, b_i \ leq N
* 1 \ leq t_i \ leq 2
* 1 \ leq v_i \ leq N
* The graph given is a tree.
* When t_i = 2, the vertex v_i is always white.



Input example


10 3
1 2
twenty five
2 6
14
13
3 7
3 8
3 9
9 10
13
twenty one
2 8


Output example


Five
1






Example

Input

10 3
1 2
2 5
2 6
1 4
1 3
3 7
3 8
3 9
9 10
1 3
2 1
2 8


Output

5
1
#include <iostream>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <algorithm>
#define llint long long
#define inf 1e18
#define mod 1000000007

using namespace std;
typedef pair<llint, llint> P;

// range-add, range-min query
 
struct SegTree{
	int size;
	vector<llint> seg, delay;
	
	SegTree(){}
	SegTree(int size){
		this->size = size;
		seg.resize(1<<(size+1));
		delay.resize(1<<(size+1));
	}
	
	void init()
	{
		for(int i = 0; i < (1<<(size+1)); i++){
			seg[i] = 0;
			delay[i] = 0;
		}
	}
	
	void eval(int l, int r, int k)
	{
		if(delay[k]){
			seg[k] += delay[k] * (r-l+1);  //総和クエリのときは区間幅を乗じる必要がある
			if(l < r){
				delay[k*2] += delay[k];
				delay[k*2+1] += delay[k];
			}
			delay[k] = 0;
		}
	}
	
	void update(int i, llint val)
	{
		i += (1 << size);
		seg[i] = val;
		while(i > 1){
			i /= 2;
			seg[i] = (seg[i*2] + seg[i*2+1]);
		}
	}
	
	void add(int a, int b, int k, int l, int r, llint val)
	{
		eval(l, r, k);
		
		if(b < l || r < a) return;
		if(a <= l && r <= b){
			delay[k] += val;
			eval(l, r, k);
			return;
		}
		add(a, b, k*2, l, (l+r)/2, val);
		add(a, b, k*2+1, (l+r)/2+1, r, val);
		seg[k] = (seg[k*2] + seg[k*2+1]);
	}
	void add(int a, int b, llint val){
		if(a > b) return;
		add(a, b, 1, 0, (1<<size)-1, val);
	}
 
	llint query(int a, int b, int k, int l, int r)
	{
		eval(l, r, k);
		
		if(b < l || r < a) return 0;
		if(a <= l && r <= b) return seg[k];
		llint lval = query(a, b, k*2, l, (l+r)/2);
		llint rval = query(a, b, k*2+1, (l+r)/2+1, r);
		return (lval + rval);
	}
	llint query(int a, int b)
	{
		if(a > b) return 0;
		return query(a, b, 1, 0, (1<<size)-1);
	}
};

struct HLD{
	int V, logV;
	vector<P> mp;
	map<P, int> mp2;
	vector<P> parent;
	
	//subtree of v is [pre_order[v], back_order[v]]
	vector<int> pre_order;
	vector<int> back_order;
	
	int order;
	int global_id, local_id;
	vector<int> size, depth;
	vector<vector<int> > prev;
	
	HLD(){}
	
	void predfs(vector<int> G[], int v, int p, int d)
	{
		size[v] = 1, depth[v] = d, prev[v][0] = p;
		for(int i = 0; i < G[v].size(); i++){
			if(G[v][i] == p) continue;
			predfs(G, G[v][i], v, d+1);
			size[v] += size[G[v][i]];
		}
	}
	void maindfs(vector<int> G[], int v, int p)
	{
		mp[v] = make_pair(global_id, local_id);
		mp2[make_pair(global_id, local_id)] = v;
		pre_order[v] = ++order;
		
		if(G[v].size() == 1 && G[v][0] == p){
			back_order[v] = order;
			return;
		}
		
		vector<P> vec;
		for(int i = 0; i < G[v].size(); i++){
			if(G[v][i] == p) continue;
			vec.push_back(make_pair(size[G[v][i]], G[v][i]));
		}
		sort(vec.rbegin(), vec.rend());
		
		local_id++;
		if(vec.size() >= 1) maindfs(G, vec[0].second, v);
			
		for(int i = 1; i < vec.size(); i++){
			parent.push_back(mp[v]);
			global_id++, local_id = 0;
			maindfs(G, vec[i].second, v);
		}
		back_order[v] = order;
	}
	int getLCA(int u, int v){
		int x = u, y = v;
		if(depth[y] > depth[x]) swap(x, y);
		
		for(int i = logV-1; i >= 0; i--){
			if(depth[x] - (1<<i) >= depth[y]) x = prev[x][i];
		}
		if(x == y) return x;
		for(int i = logV-1; i >= 0; i--){
			if(prev[x][i] != prev[y][i]){
				x = prev[x][i];
				y = prev[y][i];
			}
		}
		x = prev[x][0];
		return x;
	}
	void pathcalc(int v, int lca, vector<pair<int, P> > &dest)
	{
		int gid = mp[v].first, lid = mp[v].second;
		int Gid = mp[lca].first, Lid = mp[lca].second;
		
		while(Gid != gid){
			dest.push_back(make_pair(gid, make_pair(0, lid)));
			int ngid = parent[gid].first, nlid = parent[gid].second;
			gid = ngid, lid = nlid;
		}
		dest.push_back(make_pair(gid, make_pair(Lid, lid)));
	}
	
	void init(vector<int> G[], int V) // The tree must be 1-indexed.
	{
		this->V = V, logV = 0;
		for(int t = V; t; t/=2) logV++;
		prev.resize(V+1);
		for(int i = 0; i <= V; i++) prev[i].resize(logV);
		
		size.resize(V+1), depth.resize(V+1);
		predfs(G, 1, 0, 0);
		
		prev[0][0] = 0;
		for(int i = 1; i < logV; i++){
			for(int j = 1; j <= V; j++){
				prev[j][i] = prev[prev[j][i-1]][i-1];
			}
		}
		
		mp.resize(V+1), mp2.clear();
		parent.clear(), parent.push_back(make_pair(-1, -1));
		pre_order.resize(V+1), back_order.resize(V+1);
		global_id = local_id = 0, order = 0;
		
		maindfs(G, 1, 0);
	}
	
	void path(int u, int v, vector<pair<int, P> > &dest)
	{
		dest.clear();
		int lca = getLCA(u, v);
		pathcalc(u, lca, dest);
		pathcalc(v, lca, dest);
		
		pair<int, P> p = make_pair(mp[lca].first, make_pair(mp[lca].second, mp[lca].second));
		for(int i = 0; i < dest.size(); i++){
			if(dest[i] == p){
				dest.erase(dest.begin()+i);
				return ;
			}
		}
	}
	
	void getPath(int u, int v, vector<P> &dest) //transform an u-v path into intervals[l, r] on segtree.
	{
		vector<pair<int, P> > src;
		path(u, v, src);
		
		dest.clear();
		for(int i = 0; i < src.size(); i++){
			int u = mp2[make_pair(src[i].first, src[i].second.first)], v = mp2[make_pair(src[i].first, src[i].second.second)];
			dest.push_back(make_pair(pre_order[u], pre_order[v]));
		}
	}
};

llint n, Q;
vector<int> G[100005];
bool black[100005];
llint cut[100005];
HLD hld;
SegTree seg(18), seg2(18);

llint get(llint v)
{
	llint p = v;
	for(int i = hld.logV-1; i >= 0; i--){
		llint pp = hld.prev[hld.prev[p][i]][0];
		if(seg.query(hld.pre_order[v], hld.pre_order[v]) - seg.query(hld.pre_order[pp], hld.pre_order[pp]) == 0) p = hld.prev[p][i];
	}
	if(p == 0) p = 1;
	return p;
}

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> Q;
	llint u, v;
	for(int i = 1; i <= n-1; i++){
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	hld.init(G, n);
	seg.init(), seg2.init();
	
	//for(int i = 1; i <= n; i++) cout << hld.size[i] + seg2.query(hld.pre_order[i], hld.back_order[i]) << " "; cout << endl;
	
	llint t;
	for(int q = 1; q <= Q; q++){
		cin >> t >> v;
		if(t == 1){
			if(!black[v]){
				llint r = max(1, hld.prev[get(v)][0]);
				llint x = hld.size[v] + seg2.query(hld.pre_order[v], hld.back_order[v]);
				llint p = hld.prev[v][0], rp = hld.prev[r][0];
				seg2.add(hld.pre_order[p], hld.pre_order[p], -x), seg2.add(hld.pre_order[rp], hld.pre_order[rp], x);
				black[v] = true;
				seg.add(hld.pre_order[v], hld.back_order[v], 1);
				//cout << v << " " << hld.pre_order[v] << " " << hld.back_order[v] << endl;
			}
			else{
				black[v] = false;
				seg.add(hld.pre_order[v], hld.back_order[v], -1);
				llint r = max(1, hld.prev[get(v)][0]);
				llint x = hld.size[v] + seg2.query(hld.pre_order[v], hld.back_order[v]);
				llint p = hld.prev[v][0], rp = hld.prev[r][0];
				seg2.add(hld.pre_order[p], hld.pre_order[p], x), seg2.add(hld.pre_order[rp], hld.pre_order[rp], -x);
			}
		}
		else{
			llint r = get(v);
			cout << hld.size[r] + seg2.query(hld.pre_order[r], hld.back_order[r]) << endl;
		}
		
		/*for(int i = 1; i <= n; i++) cout << max(1, hld.prev[get(i)][0]) << " "; cout << endl;
		for(int i = 1; i <= n; i++) cout << hld.size[i] + seg2.query(hld.pre_order[i], hld.back_order[i]) << " "; cout << endl;
		for(int i = 1; i <= n; i++) cout << seg.query(hld.pre_order[i], hld.pre_order[i]) << " "; cout << endl;*/
	}

	return 0;
}
