Problem:
Problem I: Tree-Light

Problem

あなたはツリーライトというツリー状の照明器具を買ってきた。

この照明器具にはn個の接点があり、それぞれ0からn−1までの番号がついている。各接点は10段階の明るさを表現できる電球と、電球の状態を切り替えるための装置で構成されている。最初、すべての接点の電球の明るさは0である。

また、接点と接点の間にはケーブル線がある。すべての接点はn−1本のケーブル線によって繋がれており、接点0を上にして吊り下げられる。ここで、接点iから下方向に0本以上のケーブル線を介して、接点iと繋がる接点の集合を、接点iを根とした部分木と呼ぶ。

あなたはこの照明器具に対し、以下のいずれかの行動をとる。

count(r, x, y): 接点rを根とした部分木に含まれる接点の電球の中で、明るさがx以上y以下になっている電球の数を数える。

change(r, x, y): 接点rを根とした部分木に含まれる接点の電球の中で、明るさがちょうどxになっているすべての電球の明るさをyに変更する。

q回の行動が与えられるので、count(r, x, y)が与えられるたびにその時点での電球の数を出力せよ。

Input

入力は以下の形式で与えられる。

n q
u1 v1
u2 v2
...
un−1 vn−1
t1 r1 x1 y1
t2 r2 x2 y2
...
tq rq xq yq

1行目にツリーライトを構成する接点の数n、あなたのとる行動の数qが空白区切りで与えられる。

続くn−1行にはケーブル線の情報が空白区切りで与えられる。i番目のケーブル線の情報は、ケーブル線iが接点uiを上にして、接点uiと接点viを繋ぐことを表す。

n+1行目以降のq行にはあなたのとる行動が空白区切りで与えられる。ti = 1ならcount(ri, xi, yi)を、ti = 2ならchange(ri, xi, yi)を表す。

Constraints

1 ≤ n ≤ 105

1 ≤ q ≤ 105

0 ≤ ui, vi, ri ≤ n−1 (ui ≠ vi)

0 ≤ xi, yi ≤ 9 (ti = 1の時xi ≤ yi)

Output

各count(ri, xi, yi)について、その答えを1行に出力する。

Sample Input 1

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

Sample Output 1

7
7
3

Sample Input 2

7 5
0 1
1 2
2 3
0 4
4 5
5 6
2 1 0 5
2 4 0 6
2 3 5 6
2 5 6 5
1 0 0 5

Sample Output 2

5

Solution in C++14 (judge verdict: Accepted)

#include<iostream>
#include<vector>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<utility>
#include<set>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
typedef vector<int> vec;
typedef long double ld;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define stop char nyaa;cin>>nyaa;

struct SegT {
private:
	int n; vector<vec> node;
	vector<vec> lazy;
	vec e;
public:
	SegT(int sz) {
		n = 1;
		while (n < sz)n <<= 1;
		vec t(10, 0);
		node.resize(2 * n - 1, t);
		e.resize(10);
		rep(i, 10) {
			e[i] = i;
		}
		lazy.resize(2 * n - 1, e);
		rep(i, sz) {
			node[i + n - 1][0]++;
		}
		per(i, n - 1) {
			node[i] = f(node[2 * i + 1], node[2 * i + 2]);
		}
	}
	vec f(vec &a, vec &b) {
		vec ret(10,0);
		rep(i, 10) {
			ret[i] = a[i] + b[i];
		}
		return ret;
	}
	//lazy & lazy
	vec g(vec &a, vec &b) {
		vec ret(10);
		rep(i, 10) {
			ret[i] = a[b[i]];
		}
		return ret;
	}
	void eval(int k, int l, int r) {
		vec nex(10, 0);
		rep(i, 10) {
			nex[lazy[k][i]] += node[k][i];
		}
		node[k] = nex;
		if (r - l > 1) {
			lazy[2 * k + 1] = g(lazy[k], lazy[2 * k + 1]);
			lazy[2 * k + 2] = g(lazy[k], lazy[2 * k + 2]);
		}
		lazy[k] = e;
	}
	void update(int fr, int to, int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = n;
		eval(k, l, r);
		if (r <= a || b <= l)return;
		if (a <= l && r <= b) {
			rep(i, 10) {
				if (lazy[k][i] == fr)lazy[k][i] = to;
			}
			eval(k, l, r);
		}
		else {
			update(fr, to, a, b, k * 2 + 1, l, (l + r) / 2);
			update(fr, to, a, b, k * 2 + 2, (l + r) / 2, r);
			node[k] = f(node[k * 2 + 1], node[k * 2 + 2]);
		}
	}
	int query(int le,int ri,int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = n;
		eval(k, l, r);
		if (r <= a || b <= l)return 0;
		if (a <= l && r <= b) {
			int ret = 0;
			Rep(i, le, ri+1) {
				ret += node[k][i];
			}
			return ret;
		}
		else {
			int vl = query(le,ri,a, b, k * 2 + 1, l, (l + r) / 2);
			int vr = query(le,ri,a, b, k * 2 + 2, (l + r) / 2, r);
			return vl + vr;
		}
	}
	void call() {
		rep(i, 7) {
			query(0, 9, i, i + 1);
			cout << i << endl;
			rep(j, 10) {
				cout << node[i+n-1][j];
			}
			cout << endl;
		}
	}
};

int trans[1 << 17];
int ri[1 << 17];
vector<int> G[1 << 17];

int cur = 0;
void dfs(int id, int fr) {
	trans[id] = cur; cur++;
	rep(j, G[id].size()) {
		int to = G[id][j];
		if (to == fr)continue;
		dfs(to, id);
	}
	ri[trans[id]] = cur;
}

void solve() {
	int n, q; cin >> n >> q;
	rep(i, n-1) {
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	dfs(0, -1);
	SegT st(n);
	rep(i, q) {
		int t, r, x, y; cin >> t >> r >> x >> y;
		if (t == 1) {
			r = trans[r];
			int ans = st.query(x, y, r, ri[r]);
			cout << ans << endl;
		}
		else {
			r = trans[r];
			st.update(x, y, r, ri[r]);
		}
		//st.call();
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(6);
	solve();
	//stop
		return 0;
}