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
u
1
v
1
u
2
v
2
...
u
n−1
v
n−1
t
1
r
1
x
1
y
1
t
2
r
2
x
2
y
2
...
t
q
r
q
x
q
y
q
1行目にツリーライトを構成する接点の数
n
、あなたのとる行動の数
q
が空白区切りで与えられる。
続く
n−1
行にはケーブル線の情報が空白区切りで与えられる。
i
番目のケーブル線の情報は、ケーブル線
i
が接点
u
i
を上にして、接点
u
i
と接点
v
i
を繋ぐことを表す。
n+1
行目以降の
q
行にはあなたのとる行動が空白区切りで与えられる。
t
i
= 1
なら
count(r
i
, x
i
, y
i
)
を、
t
i
= 2
なら
change(r
i
, x
i
, y
i
)
を表す。
Constraints
1 ≤ n ≤ 10
5
1 ≤ q ≤ 10
5
0 ≤ u
i
, v
i
, r
i
≤ n−1 (u
i
≠ v
i
)
0 ≤ x
i
, y
i
≤ 9 (t
i
= 1
の時
x
i
≤ y
i
)
Output
各
count(r
i
, x
i
, y
i
)
について、その答えを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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for(int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2018/07/05  Problem: AOJ 3008 / Link: https://onlinejudge.u-aizu.ac.jp/challenges/search/volumes/3008  ----- */
/* ------問題------

あなたはツリーライトというツリー状の照明器具を買ってきた。
この照明器具には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)が与えられるたびにその時点での電球の数を出力せよ。

-----問題ここまで----- */
/* -----解説等-----

なんでバグるんや…
まず部分木操作しか無いので、HLDじゃなくてeulertourでよい。
次に列のときの更新を考える。
これは写像を扱っていると気づくことができるので、写像を保持した状態で個数を移動できるようにすれば良い。
遅延型を保持できるようにいい感じにすればよい。

----解説ここまで---- */


struct Node {
	Node(long long x = 10) { FOR(i, 0, 11)val[i] = 0; val[x] = 1; }
	long long val[11];
};
struct Lazy {
	Lazy() :set(0) { FOR(i, 0, 10)lazyval[i] = i; } // lazy e

	bool set;
	long long lazyval[11];
};
long long out_range = 10; // queryの範囲外の値 , mergeを考慮


typedef long long ll;
struct LazySegTreeP {

	long long N;
	vector<Node> dat;
	vector<Lazy> lazy;

	inline Node merge(Node& a, Node& b) { // node⊕node
		Node node(10);
		FOR(i, 0, 10) {
			node.val[i] = a.val[i] + b.val[i];
		}
		return node;
	} //台数構造

	  // 命令を下のノードにpush
	void lazy_push(ll k, ll queryL, ll queryR) { // node⊕lazy
		if (lazy[k].set == 0)return; // 命令なし
		// L to N
		Node ret(10);
		FOR(i, 0, 10) {
			ret.val[lazy[k].lazyval[i]] += dat[k].val[i];
		}
		FOR(i, 0, 10) {
			dat[k].val[i] = ret.val[i];
		}

		if (k < N - 1) {
			lazy_set(2 * k + 1, lazy[k]);
			lazy_set(2 * k + 2, lazy[k]); //下にlazy[k].lazyvalをそのまま伝搬
		}

		//lazy reset
		FOR(i, 0, 10) {
			lazy[k].lazyval[i] = i;
		}


		lazy[k].set = 0; // 子に命令を伝搬させたので、命令を空にする
	}

	// ノードがクエリと一致したとき遅延命令をセット
	inline void lazy_set(ll k, const Lazy& val) { // lazy⊕lazy
		lazy[k].set = 1;
		Lazy nx;
		FOR(i, 0, 10) {
			nx.lazyval[i] = val.lazyval[lazy[k].lazyval[i]];
		}

		FOR(i, 0, 10) {
			lazy[k].lazyval[i] = nx.lazyval[i];
		}
	}


	//--------------setting--------------//

	inline void fix(ll k) { // ノードkに対応する　値に修正 merge的な
		dat[k] = merge(dat[k * 2 + 1], dat[k * 2 + 2]);
	}

	LazySegTreeP(int _N) {
		N = 1;
		while (N < _N)N *= 2;
		dat = vector<Node>(N * 2 - 1);	// max値を入れておく、書き換えupdateはいいが加算addに注意
		lazy = vector<Lazy>(N * 2 - 1);	// 遅延評価管理フラグ、遅延評価値にならない値をNILにする
	}

	LazySegTreeP(vector<int>& a, int _N) { //なにかしらで初期化できるならする。(クエリが後でも処理できるときなど)
		N = 1;
		while (N < _N)N *= 2;
		dat = vector<Node>(N * 2 - 1);
		lazy = vector<Lazy>(N * 2 - 1);	// 遅延評価管理フラグ、遅延評価値にならない値をNILにする
		for (int i = 0; i < _N; ++i)dat[i + N - 1] = (Node{ a[i] });
		build();
	}
	void build() { for (int i = N - 2; i >= 0; i--) dat[i] = merge(dat[2 * i + 1], dat[2 * i + 2]); }//mergeして木の作成

	~LazySegTreeP() { vector<Node>().swap(dat); vector<Lazy>().swap(lazy); }


	// 区間[queryL,queryR)をvalで塗りつぶす
	inline void lazy_update(ll queryL, ll queryR, Lazy& val, ll k = 0, ll nodeL = 0, ll nodeR = -1) {
		if (nodeR == -1)nodeR = N;
		lazy_push(k, nodeL, nodeR);// とりあえず遅延評価分を下のノードに伝播


		if (nodeR <= queryL || queryR <= nodeL) { return; }// クエリ区間とノード区間が交差していないなら、これ以上、処理する意味はない
		if (queryL <= nodeL && nodeR <= queryR) {// ノード区間がクエリ区間に完全に覆われたら、遅延命令をセットして、さっさと帰る
			lazy_set(k, val); // 命令をセット
			lazy_push(k, nodeL, nodeR); // 命令をpush
			return;
		}

		// 中途半端に区間が被るときは下のノードにお任せ ノードが下がるときには命令をpushする

		ll nodeM = (nodeL + nodeR) / 2;
		lazy_update(queryL, queryR, val, k * 2 + 1, nodeL, nodeM);
		lazy_update(queryL, queryR, val, k * 2 + 2, nodeM, nodeR);

		fix(k);	// 下のノードの処理が終了して ノードが上がるときにはその前に情報をfixする
		return;
	}

	// 区間[queryL, queryR)のクエリ
	Node query(ll queryL, ll queryR, ll k, ll nodeL, ll nodeR) {

		lazy_push(k, nodeL, nodeR);// とりあえずpushして伝播

		if (nodeR <= queryL || queryR <= nodeL) { return Node(out_range); }	// クエリ区間とノード区間が交差していない => 影響しない値を返す
		if (queryL <= nodeL && nodeR <= queryR) { return dat[k]; } // ノード区間がクエリ区間に完全に覆われた

		ll nodeM = (nodeL + nodeR) / 2;
		Node vl = query(queryL, queryR, k * 2 + 1, nodeL, nodeM);
		Node vr = query(queryL, queryR, k * 2 + 2, nodeM, nodeR);
		//fix(k); // いらん(はず)
		return merge(vr, vl);
	}
	inline Node query(int a, int b) {
		return query(a, b, 0, 0, N);
	}
};

PII et[200000]; // V: seg.query(et[v].first, et[v].second)
void calc(const vector<vector<int>>&G, int root = 0) {
	int k = 0;
	stack<PII> s;
	s.push(PII(root, -1));
	while (!s.empty()) {
		PII q = s.top(); s.pop();
		int x = q.first, p = q.second;
		if (x < 0 || (!x&&p > 0)) {
			et[-x].second = k;
			continue;
		}
		s.push(PII(-x, -p));
		et[x].first = k++;
		for (int i = 0; i < (int)G[x].size(); i++) {
			int y = G[x][i];
			if (y == p) continue;
			s.push(PII(y, x));
		}
	}
}

//

int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	int N, Q;
	cin >> N >> Q;
	VVI G(N);
	FOR(i, 0, N - 1) {
		int a, b;
		cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	calc(G);
	//FOR(i, 0, N) {
	//	cout << et[i].first << "," << et[i].second << endl;
	//}
	//cout << "euler" << endl;
	VI na(N, 0);
	LazySegTreeP seg(na, N); //default :0
	//FOR(i, 0, 100) {
	//	int a; cin >> a;
	//	Node nd = seg.query(et[a].first, et[a].second);
	//	FOR(k, 0, 11) {
	//		cout << k << ":=" << nd.val[k] << " ";
	//	}cout << endl;
	//}


	FOR(q, 0, Q) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		if (a == 1) { // query
			Node nd = seg.query(et[b].first, et[b].second);
			int ans = 0;
			FOR(k, c, d + 1) {
				//cout << k << ":=" << nd.val[k] << " ";
				ans += nd.val[k];
			}//cout << endl;
			cout << ans << endl;
		}
		else { // change
			Lazy fromto;
			fromto.lazyval[c] = d;
			//cout << "insert:";
			//FOR(i, 0, 10)cout << fromto.lazyval[i] << " ";
			//cout << endl;
			seg.lazy_update(et[b].first, et[b].second, fromto);
		}
		//cout << "deb" << endl;
		//FOR(i, 0, N) {
		//	Node nd = seg.query(i, i + 1);
		//	FOR(k, 0, 11)cout << nd.val[k] << " ";
		//	cout << endl;
		//}

	}


	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 57236
final_rank: 2

code_snippet: // AOJ #3008 Tree-Light
// 2025.3.24

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

const int D = 10;
vector<vector<int>> adj;
vector<int> tin, tout, eul;
int timer = 0;
void dfs(int v, int p) {
    tin[v] = timer;
    eul[timer++] = v;
    for (int w : adj[v]) {
        if(w == p) continue;
        dfs(w, v);
    }
    tout[v] = timer;
}

struct Node { int cnt[D], lz[D]; };
vector<Node> seg;

void initLazy(int idx) {
    for (int i = 0; i < D; i++) seg[idx].lz[i] = i;
}

void pull(int idx) {
    for (int i = 0; i < D; i++) seg[idx].cnt[i] = seg[idx*2].cnt[i] + seg[idx*2+1].cnt[i];
}

void applyLazy(int idx, const int f[D]) {
    int tmp[D] = {0};
    for (int v = 0; v < D; v++) tmp[ f[v] ] += seg[idx].cnt[v];
    for (int v = 0; v < D; v++) seg[idx].cnt[v] = tmp[v];
    int newL[D];
    for (int v = 0; v < D; v++) newL[v] = f[ seg[idx].lz[v] ];
    for (int v = 0; v < D; v++) seg[idx].lz[v] = newL[v];
}

void pushDown(int idx) {
    int f[D];
    for (int v = 0; v < D; v++) f[v] = seg[idx].lz[v];
    applyLazy(idx*2, f);
    applyLazy(idx*2+1, f);
    initLazy(idx);
}

void build(int idx, int l, int r) {
    initLazy(idx);
    if(r - l == 1) {
        for (int i = 0; i < D; i++) seg[idx].cnt[i] = 0;
        seg[idx].cnt[0] = 1;
        return;
    }
    int m = (l + r) / 2;
    build(idx*2, l, m);
    build(idx*2+1, m, r);
    for (int i = 0; i < D; i++) seg[idx].cnt[i] = seg[idx*2].cnt[i] + seg[idx*2+1].cnt[i];
}

void update(int idx, int l, int r, int ql, int qr, int x, int y) {
    if(ql >= r || qr <= l) return;
    if(ql <= l && r <= qr) {
        int f[D];
        for (int i = 0; i < D; i++) f[i] = i;
        f[x] = y;
        applyLazy(idx, f);
        return;
    }
    pushDown(idx);
    int m = (l + r) / 2;
    update(idx*2, l, m, ql, qr, x, y);
    update(idx*2+1, m, r, ql, qr, x, y);
    pull(idx);
}

int query(int idx, int l, int r, int ql, int qr, int a, int b) {
    if(ql >= r || qr <= l) return 0;
    if(ql <= l && r <= qr) {
        int s = 0;
        for (int i = a; i <= b; i++) s += seg[idx].cnt[i];
        return s;
    }
    pushDown(idx);
    int m = (l + r) / 2;
    return query(idx*2, l, m, ql, qr, a, b) + query(idx*2+1, m, r, ql, qr, a, b);
}

int main(){
    int n = Cin(), q = Cin();
    adj.assign(n, {});
    tin.resize(n); tout.resize(n); eul.resize(n);
    for (int i = 1; i < n; i++){
        int u = Cin(), v = Cin();
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(0, -1);
    seg.resize(4 * n);
    build(1, 0, n);

    while(q--){
        int t = Cin(), r = Cin(), x = Cin(), y = Cin();
        int L = tin[r], R = tout[r];
        if(t & 1) Cout(query(1, 0, n, L, R, x, y));
        else update(1, 0, n, L, R, x, y);
    }
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 45592
final_rank: 1

code_snippet: // AOJ #3008 Tree-Light
// 2025.3.24

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

const int D = 10;

vector<vector<int>> adj;
vector<int> tin, tout, eul;
int timer = 0;

void dfs(int v, int p) {
    tin[v] = timer;
    eul[timer++] = v;
    for(auto w : adj[v]) {
        if(w == p) continue;
        dfs(w, v);
    }
    tout[v] = timer;
}

struct Node { int cnt[D], laz[D]; };
vector<Node> seg;
void initLazy(int idx) {
    for (int i = 0; i < D; i++) seg[idx].laz[i] = i;
}

void pull(int idx) {
    for (int i = 0; i < D; i++) seg[idx].cnt[i] = seg[idx*2].cnt[i] + seg[idx*2+1].cnt[i];
}

void applyLazy(int idx, int f[D]) {
    int tmp[D] = {0};
    for (int v = 0; v < D; v++) tmp[f[ seg[idx].laz[v] ]] += seg[idx].cnt[v];
    for (int v = 0; v < D; v++) seg[idx].cnt[v] = tmp[v];
    for (int v = 0; v < D; v++) seg[idx].laz[v] = f[ seg[idx].laz[v] ];
}

void pushDown(int idx) {
    for (int i = 0; i < D; i++) {
        if(seg[idx].laz[i] != i) {
            int f[D];
            for (int j = 0; j < D; j++) f[j] = (j == i ? seg[idx].laz[i] : j);
            applyLazy(idx*2, f);
            applyLazy(idx*2+1, f);
        }
    }
    initLazy(idx);
}

void build(int idx, int l, int r) {
    initLazy(idx);
    if(r - l == 1) {
        for (int i = 0; i < D; i++) seg[idx].cnt[i] = 0;
        seg[idx].cnt[0] = 1;
        return;
    }
    int m = (l + r) / 2;
    build(idx*2, l, m);
    build(idx*2+1, m, r);
    for (int i = 0; i < D; i++) seg[idx].cnt[i] = seg[idx*2].cnt[i] + seg[idx*2+1].cnt[i];
}

void update(int idx, int l, int r, int ql, int qr, int x, int y) {
    if(ql >= r || qr <= l) return;
    if(ql <= l && r <= qr) {
        int f[D];
        for (int i = 0; i < D; i++) f[i] = i;
        f[x] = y;
        applyLazy(idx, f);
        return;
    }
    pushDown(idx);
    int m = (l + r) / 2;
    update(idx*2, l, m, ql, qr, x, y);
    update(idx*2+1, m, r, ql, qr, x, y);
    pull(idx);
}

int query(int idx, int l, int r, int ql, int qr, int a, int b) {
    if(ql >= r || qr <= l) return 0;
    if(ql <= l && r <= qr) {
        int s = 0;
        for (int i = a; i <= b; i++) s += seg[idx].cnt[i];
        return s;
    }
    pushDown(idx);
    int m = (l + r) / 2;
    return query(idx*2, l, m, ql, qr, a, b) + query(idx*2+1, m, r, ql, qr, a, b);
}

int main(){
    int n = Cin(), q = Cin();
    adj.assign(n, {});
    tin.resize(n); tout.resize(n); eul.resize(n);
    for (int i = 1; i < n; i++) {
        int u = Cin(), v = Cin();
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(0, -1);
    seg.resize(4 * n);
    build(1, 0, n);

    while(q--){
        int t = gc(); gc();
        int r = Cin(), x = Cin(), y = Cin();
        int L = tin[r], R = tout[r];
        if(t & 1) Cout(query(1, 0, n, L, R, x, y));
        else update(1, 0, n, L, R, x, y);
    }
    return 0;
}
accuracy: 0.25
time_ms: 130
memory_kb: 41104
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef vector<int> BrightnessCount;
typedef vector<short> BrightnessMapping;
const BrightnessCount InitialCount{ 0,0,0,0,0,0,0,0,0,0,1 };
const BrightnessMapping InitialMapping{ 0,1,2,3,4,5,6,7,8,9,10 };

struct SegmentNode {
    BrightnessCount count;  // Counts of bulbs with each brightness level
    BrightnessMapping mapping;  // Lazy propagation array for brightness updates
    SegmentNode() : count(InitialCount) {
        mapping = InitialMapping;
    }
};

int numberOfNodes, numberOfQueries;
struct SegmentTree {
    int size;
    vector<SegmentNode> tree;

    SegmentTree(int n) : size(1) {
        while (size < n) size *= 2;
        tree.resize(2 * size);
        for (int i = size; i < size + numberOfNodes; ++i) {
            tree[i].count = BrightnessCount{ 1,0,0,0,0,0,0,0,0,0,0 };
        }
        for (int i = size - 1; i >= 1; --i) {
            updateNode(i);
        }
    }

    void applyPendingUpdates() {
        for (int i = size - 1; i >= 1; --i) {
            updateNode(i);
        }
    }

    BrightnessMapping combineMappings(const BrightnessMapping& left, const BrightnessMapping& right) {
        BrightnessMapping result(left);
        for (int i = 0; i < 11; ++i) {
            result[i] = right[result[i]];
        }
        return result;
    }

    void applyMapping(int node, int start, int end) {
        BrightnessCount newCount(11);
        for (int i = 0; i < 11; ++i) {
            newCount[tree[node].mapping[i]] += tree[node].count[i];
        }
        tree[node].count = newCount;
    }

    BrightnessCount mergeCounts(const BrightnessCount& left, const BrightnessCount& right) {
        BrightnessCount result(left);
        for (int i = 0; i < 11; ++i) {
            result[i] += right[i];
        }
        return result;
    }

    inline void evaluateNode(int node, int start, int end) {
        applyMapping(node, start, end);
        if (node < size) {
            tree[2 * node].mapping = combineMappings(tree[2 * node].mapping, tree[node].mapping);
            tree[2 * node + 1].mapping = combineMappings(tree[2 * node + 1].mapping, tree[node].mapping);
        }
        tree[node].mapping = InitialMapping;
    }

    inline void updateNode(int node) {
        tree[node].count = mergeCounts(tree[2 * node].count, tree[2 * node + 1].count);
    }

    void update(int l, int r, const BrightnessMapping& newMapping, int node = 1, int start = 0, int end = -1) {
        if (end == -1) end = size;
        evaluateNode(node, start, end);

        if (end <= l || r <= start) return;
        if (l <= start && end <= r) {
            tree[node].mapping = combineMappings(tree[node].mapping, newMapping);
            evaluateNode(node, start, end);
            return;
        }

        int mid = (start + end) / 2;
        update(l, r, newMapping, 2 * node, start, mid);
        update(l, r, newMapping, 2 * node + 1, mid, end);
        updateNode(node);
    }

    BrightnessCount query(int l, int r, int node = 1, int start = 0, int end = -1) {
        if (end == -1) end = size;
        evaluateNode(node, start, end);

        if (end <= l || r <= start) return InitialCount;
        if (l <= start && end <= r) return tree[node].count;

        int mid = (start + end) / 2;
        BrightnessCount leftResult = query(l, r, 2 * node, start, mid);
        BrightnessCount rightResult = query(l, r, 2 * node + 1, mid, end);
        updateNode(node);
        return mergeCounts(leftResult, rightResult);
    }
};

void performDFS(const vector<vector<int>>& adjacencyList, const int currentNode, const int parentNode, vector<int>& entryTime, vector<int>& exitTime, int& counter) {
    entryTime[currentNode] = counter++;
    for (auto neighbor : adjacencyList[currentNode]) {
        if (neighbor == parentNode) continue;
        performDFS(adjacencyList, neighbor, currentNode, entryTime, exitTime, counter);
    }
    exitTime[currentNode] = counter;
}

int main() {
    cin >> numberOfNodes >> numberOfQueries;
    vector<vector<int>> adjacencyList(numberOfNodes);
    vector<int> entryTime(numberOfNodes), exitTime(numberOfNodes);

    for (int i = 0; i < numberOfNodes - 1; ++i) {
        int u, v;
        cin >> u >> v;
        adjacencyList[u].push_back(v);
        adjacencyList[v].push_back(u);
    }

    int counter = 0;
    performDFS(adjacencyList, 0, -1, entryTime, exitTime, counter);

    SegmentTree segmentTree(numberOfNodes);

    while (numberOfQueries--) {
        int operationType, node, brightnessStart, brightnessEnd;
        cin >> operationType >> node >> brightnessStart >> brightnessEnd;

        if (operationType == 1) {
            BrightnessCount result = segmentTree.query(entryTime[node], exitTime[node]);
            int count = accumulate(result.begin() + brightnessStart, result.begin() + brightnessEnd + 1, 0);
            cout << count << endl;
        } else {
            BrightnessMapping mapping(11);
            iota(mapping.begin(), mapping.end(), 0);
            mapping[brightnessStart] = brightnessEnd;
            segmentTree.update(entryTime[node], exitTime[node], mapping);
        }
    }

    return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 53996
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<string.h>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx * 4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		tree[k].is_lazy = 0;
		return;
	}
	int lazy[11], sum[11];
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1].sum[i] = sum[i];
		tree[k << 1].lazy[i] = lazy[i];
	}
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1|1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1|1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1|1].sum[i] = sum[i];
		tree[k << 1|1].lazy[i] = lazy[i];
	}
	for (int i = 0; i < 10; i++) {
		tree[k].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	return;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x]) || (x == y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		for (int i = 0; i < 10; i++) {
			if (tree[k].lazy[i] == x) {
				tree[k].lazy[i] = y;
			}
		}
		tree[k].is_lazy = 1;
		return;
	}
	pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 1
time_ms: 340
memory_kb: 51900
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<string.h>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx * 4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	
	int lazy[11], sum[11];
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1].sum[i] = sum[i];
		tree[k << 1].lazy[i] = lazy[i];
	}
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1|1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1|1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1|1].sum[i] = sum[i];
		tree[k << 1|1].lazy[i] = lazy[i];
	}
	for (int i = 0; i < 10; i++) {
		tree[i].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	return;
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1 | 1].sum[tree[k].lazy[i]] += tree[k << 1 | 1].sum[i];
			tree[k << 1 | 1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x]) || (x == y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		for (int i = 0; i < 10; i++) {
			if (tree[k].lazy[i] == x) {
				tree[k].lazy[i] = y;
			}
		}
		tree[k].is_lazy = 1;
		return;
	}
	pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 240
memory_kb: 47040
final_rank: 15

code_snippet: #include<iostream>
#include<vector>
#include<string.h>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx * 4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		tree[k].is_lazy = 0;
		return;
	}
	int lazy[11], sum[11];
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1].sum[i] = sum[i];
		tree[k << 1].lazy[i] = lazy[i];
	}
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1|1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1|1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1|1].sum[i] = sum[i];
		tree[k << 1|1].lazy[i] = lazy[i];
	}
	for (int i = 0; i < 10; i++) {
		tree[i].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	return;
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1 | 1].sum[tree[k].lazy[i]] += tree[k << 1 | 1].sum[i];
			tree[k << 1 | 1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x]) || (x == y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		for (int i = 0; i < 10; i++) {
			if (tree[k].lazy[i] == x) {
				tree[k].lazy[i] = y;
			}
		}
		tree[k].is_lazy = 1;
		return;
	}
	pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 260
memory_kb: 47004
final_rank: 16

code_snippet: #include<iostream>
#include<vector>
#include<string.h>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx * 4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		tree[k].is_lazy = 0;
		return;
	}
	int lazy[11], sum[11];
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1].sum[i] = sum[i];
		tree[k << 1].lazy[i] = lazy[i];
	}
	memset(lazy, 0, sizeof(lazy));
	memset(sum, 0, sizeof(sum));
	for (int i = 0; i < 10; i++) {
		int x = i, y = tree[k].lazy[i];
		sum[y] += tree[k << 1|1].sum[x];
		for (int j = 0; j < 10; j++) {
			if (tree[k << 1|1].lazy[j] == x) {
				lazy[j] = y;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		tree[k << 1|1].sum[i] = sum[i];
		tree[k << 1|1].lazy[i] = lazy[i];
	}
	for (int i = 0; i < 10; i++) {
		tree[i].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	return;
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1 | 1].sum[tree[k].lazy[i]] += tree[k << 1 | 1].sum[i];
			tree[k << 1 | 1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x]) || (x == y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		for (int i = 0; i < 10; i++) {
			if (tree[k].lazy[i] == x) {
				tree[k].lazy[i] = y;
			}
		}
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 90
memory_kb: 47220
final_rank: 14

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx * 4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		tree[k].is_lazy = 0;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1 | 1].sum[tree[k].lazy[i]] += tree[k << 1 | 1].sum[i];
			tree[k << 1 | 1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k].is_lazy = 0;
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x]) || (x == y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		for (int i = 0; i < 10; i++) {
			if (tree[k].lazy[i] == x) {
				tree[k].lazy[i] = y;
			}
		}
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if (tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 50
memory_kb: 47288
final_rank: 11

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx * 4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		tree[k].is_lazy = 0;
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1 | 1].sum[tree[k].lazy[i]] += tree[k << 1 | 1].sum[i];
			tree[k << 1 | 1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	tree[k].is_lazy = 0;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x]) || (x == y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].lazy[x] = y;
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		tree[k].is_lazy = 1;
		return;
	}
	if (tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if (tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 50
memory_kb: 47040
final_rank: 10

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
int vis[mx];
void dfs(int k) {
	vis[k] = 1;
	s[k] = cnt++;
	for (auto x : son[k]) {
		if(!vis[x])dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx*4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		tree[k].is_lazy = 0;
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1|1].sum[tree[k].lazy[i]] += tree[k << 1|1].sum[i];
			tree[k << 1|1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	tree[k].is_lazy = 0;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x])||(x==y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].lazy[x] = y;
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
		son[y].push_back(x);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 40
memory_kb: 49148
final_rank: 12

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx*4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		tree[k].is_lazy = 0;
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1|1].sum[tree[k].lazy[i]] += tree[k << 1|1].sum[i];
			tree[k << 1|1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	tree[k].is_lazy = 0;
}
void change(int k, int l, int r, int x, int y) {
	if ((!tree[k].sum[x])||(x==y))return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].lazy[x] = y;
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 40
memory_kb: 47300
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx*4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		tree[k].is_lazy = 0;
		for (int i = 0; i < 10; i++)tree[k].lazy[i] = i;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1|1].sum[tree[k].lazy[i]] += tree[k << 1|1].sum[i];
			tree[k << 1|1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	tree[k].is_lazy = 0;
}
void change(int k, int l, int r, int x, int y) {
	if (!tree[k].sum[x]||x==y)return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].lazy[x] = y;
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	if (y < x)return 0;
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 40
memory_kb: 47288
final_rank: 6

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx*4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		tree[k].is_lazy = 0;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1|1].sum[tree[k].lazy[i]] += tree[k << 1|1].sum[i];
			tree[k << 1|1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	tree[k].is_lazy = 0;
}
void change(int k, int l, int r, int x, int y) {
	if (!tree[k].sum[x]||x==y)return;
	if (tree[k].l >= l && tree[k].r <= r) {
		tree[k].lazy[x] = y;
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	int ans = 0;
	if (tree[k].l >= l && tree[k].r <= r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 40
memory_kb: 47300
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
using namespace std;
const int mx = 1e5 + 10;
vector<int>son[mx];
int s[mx], e[mx];
int cnt = 1;
void dfs(int k) {
	s[k] = cnt++;
	for (auto x : son[k]) {
		dfs(x);
	}
	e[k] = cnt - 1;
}
struct node {
	int l, r;
	int sum[11] = { 0 }, lazy[11] = { 0 };
	bool is_lazy = 0;
}tree[mx*4];
void add(int k) {
	for (int i = 0; i < 10; i++) {
		tree[k].sum[i] = tree[k << 1].sum[i] + tree[k << 1 | 1].sum[i];
	}
}
void build(int k, int l, int r) {
	tree[k].l = l, tree[k].r = r, tree[k].is_lazy = 0;
	for (int i = 0; i < 10; i++)tree[k].lazy[i] = i, tree[k].sum[i] = 0;
	if (l == r) {
		tree[k].sum[0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	add(k);
}
void pushdown(int k) {
	if (tree[k].l == tree[k].r) {
		tree[k].is_lazy = 0;
		return;
	}
	for (int i = 0; i < 10; i++) {
		if (tree[k].lazy[i] != i) {
			tree[k << 1].sum[tree[k].lazy[i]] += tree[k << 1].sum[i];
			tree[k << 1].sum[i] = 0;
			tree[k << 1|1].sum[tree[k].lazy[i]] += tree[k << 1|1].sum[i];
			tree[k << 1|1].sum[i] = 0;
		}
		tree[k << 1].lazy[i] = tree[k << 1 | 1].lazy[i] = tree[k].lazy[i];
		tree[k].lazy[i] = i;
	}
	tree[k << 1].is_lazy = tree[k << 1 | 1].is_lazy = 1;
	tree[k].is_lazy = 0;
}
void change(int k, int l, int r, int x, int y) {
	if (!tree[k].sum[x]||x==y)return;
	if (tree[k].l == l && tree[k].r == r) {
		tree[k].lazy[x] = y;
		tree[k].sum[y] += tree[k].sum[x];
		tree[k].sum[x] = 0;
		tree[k].is_lazy = 1;
		return;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)change(k << 1, l, r, x, y);
	else if (l > mid)change(k << 1 | 1, l, r, x, y);
	else {
		change(k << 1, l, mid, x, y);
		change(k << 1 | 1, mid + 1, r, x, y);
	}
	add(k);
}
int query(int k, int l, int r, int x, int y) {
	int ans = 0;
	if (tree[k].l == l && tree[k].r == r) {
		for (int i = x; i <= y; i++) {
			ans += tree[k].sum[i];
		}
		return ans;
	}
	if(tree[k].is_lazy)pushdown(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if (r <= mid)ans += query(k << 1, l, r, x, y);
	else if (l > mid)ans += query(k << 1 | 1, l, r, x, y);
	else {
		ans = ans + query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
	}
	return ans;
}
int read() {
	int f = 1, k = 0;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-')f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		k = k * 10 + (c - '0');
		c = getchar();
	}
	return k * f;
}
int main() {
	int n, q, t, r, x, y;
	n = read(), q = read();
	build(1, 1, n);
	for (int i = 1; i < n; i++) {
		x = read(), y = read();
		son[x].push_back(y);
	}
	dfs(0);
	while (q--) {
		t = read(), r = read(), x = read(), y = read();
		if (t == 2)change(1, s[r], e[r], x, y);
		else printf("%d\n", query(1, s[r], e[r], x, y));
	}
}
accuracy: 0.25
time_ms: 40
memory_kb: 47296
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define int long long
#define Mid (l + r >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read() {
	char c; int num, f = 1;
	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
	return f * num;
}
const int N = 2e6 + 1009;
vector<int> ver[N];
int tree[N][11], maxn, lzt[N][11];
int n, q, siz[N], idn[N], tt;
void dfs(int x, int pre) {
	siz[x] = 1;
	idn[x] = ++tt;
	for(auto y : ver[x]) if(y != pre) {
		dfs(y, x);
		siz[x] += siz[y];
	}
}
void update(int rt) {
	for(int i = 0; i < 10; i++) 
		tree[rt][i] = tree[lson][i] + tree[rson][i];
}
void build(int l, int r, int rt) {
	for(int i = 0; i < 10; i++) lzt[rt][i] = i;
	if(l == r) {
		memset(tree[rt], 0, sizeof(tree[rt]));
		tree[rt][0] = 1;
		return ;
	}
	build(l, Mid, lson);
	build(Mid + 1, r, rson);
	update(rt);
}
void mg(int rt, int x, int y) {
	if(x == y) return ;
	tree[rt][y] += tree[rt][x];
	tree[rt][x] = 0;
	for(int i = 0; i < 10; i++) 
		if(lzt[rt][i] == x) 
			lzt[rt][i] = y;
}
void pushdown(int rt) {
	int tlzt[11];
	int ttree[11];
	memset(tlzt, 0, sizeof(tlzt));
	memset(ttree, 0, sizeof(ttree));
	for(int i = 0; i < 10; i++) {
		int x = i;
		int y = lzt[rt][i];
		ttree[y] += tree[lson][x];
		for(int j = 0; j < 10; j++) {
			if(lzt[lson][j] == x) {
				tlzt[j] = y;
			}
		}	
	}
	for(int i = 0; i < 10; i++) {
		tree[lson][i] = ttree[i];
		lzt[lson][i] = tlzt[i];
	}
	memset(tlzt, 0, sizeof(tlzt));
	memset(ttree, 0, sizeof(ttree));
	for(int i = 0; i < 10; i++) {
		int x = i;
		int y = lzt[rt][i];
		ttree[y] += tree[rson][x];
		for(int j = 0; j < 10; j++) {
			if(lzt[rson][j] == x) {
				tlzt[j] = y;
			}
		}	
	}
	for(int i = 0; i < 10; i++) {
		tree[rson][i] = ttree[i];
		lzt[rson][i] = tlzt[i];
	}
	for(int i = 0; i < 10; i++) lzt[rt][i] = i;
//	for(int i = 0; i < 10; i++) {
//		if(lzt[rt][i] != i) {
//			mg(lson, i, lzt[rt][i]);
//			mg(rson, i, lzt[rt][i]);
//			lzt[rt][i] = i;
//		}
//	}
}
void modify(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return ;
	if(L <= l && r <= R) {
		mg(rt, x, y);
		return ;
	}
	pushdown(rt);
	if(L <= Mid) modify(l, Mid, L, R, x, y, lson);
	if(Mid <  R) modify(Mid + 1, r, L, R, x, y, rson);
	update(rt);
}
int query(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return 0;
	if(L <= l && r <= R) {
		int cnt = 0;
		for(int i = x; i <= y; i++)	
			cnt += tree[rt][i];
		return cnt;
	}
	pushdown(rt);
	int cnt = 0;
	if(L <= Mid) cnt += query(l, Mid, L, R, x, y, lson);
	if(Mid <  R) cnt += query(Mid + 1, r, L, R, x, y, rson);
	return cnt;
}
signed main()
{
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	scanf("%lld%lld", &n, &q);
	for(int i = 1; i < n; i++) {
		int x, y;
		scanf("%lld%lld", &x, &y);
		x += 1; y += 1;
		ver[x].push_back(y);
		ver[y].push_back(x);
	}
	dfs(1, 1);
	build(1, n, 1);
	for(int i = 1; i <= q; i++) {
		int opt, x, l, r;
		scanf("%lld%lld%lld%lld", &opt, &x, &l, &r);
		x += 1;
		if(opt == 1) {
			printf("%lld\n", query(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1));
		} else {
			if(l == r) continue;
			modify(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1);
		}
	}
	return 0;
}
/*
5 5
0 1
1 2
1 3
2 4
2 0 6 3
2 1 0 6
2 4 5 9
1 0 0 5
2 0 4 3

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

*/
accuracy: 1
time_ms: 620
memory_kb: 112692
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define int long long
#define Mid (l + r >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read() {
	char c; int num, f = 1;
	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
	return f * num;
}
const int N = 2e6 + 1009;
vector<int> ver[N];
int tree[N][11], maxn, lzt[N][11];
int n, q, siz[N], idn[N], tt;
void dfs(int x, int pre) {
	siz[x] = 1;
	idn[x] = ++tt;
	for(auto y : ver[x]) if(y != pre) {
		dfs(y, x);
		siz[x] += siz[y];
	}
}
void update(int rt) {
	for(int i = 0; i < 10; i++) 
		tree[rt][i] = tree[lson][i] + tree[rson][i];
}
void build(int l, int r, int rt) {
	for(int i = 0; i < 10; i++) lzt[rt][i] = i;
	if(l == r) {
		memset(tree[rt], 0, sizeof(tree[rt]));
		tree[rt][0] = 1;
		return ;
	}
	build(l, Mid, lson);
	build(Mid + 1, r, rson);
	update(rt);
}
void mg(int rt, int x, int y) {
	if(x == y) return ;
	tree[rt][y] += tree[rt][x];
	tree[rt][x] = 0;
	for(int i = 0; i < 10; i++) 
		if(lzt[rt][i] == x) 
			lzt[rt][i] = y;
}
void pushdown(int rt) {
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] != i) {
			mg(lson, i, lzt[rt][i]);
			mg(rson, i, lzt[rt][i]);
			lzt[rt][i] = i;
		}
	}
}
void modify(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return ;
	if(L <= l && r <= R) {
		mg(rt, x, y);
		return ;
	}
	pushdown(rt);
	if(L <= Mid) modify(l, Mid, L, R, x, y, lson);
	if(Mid <  R) modify(Mid + 1, r, L, R, x, y, rson);
	update(rt);
}
int query(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return 0;
	if(L <= l && r <= R) {
		int cnt = 0;
		for(int i = x; i <= y; i++)	
			cnt += tree[rt][i];
		return cnt;
	}
	pushdown(rt);
	int cnt = 0;
	if(L <= Mid) cnt += query(l, Mid, L, R, x, y, lson);
	if(Mid <  R) cnt += query(Mid + 1, r, L, R, x, y, rson);
	return cnt;
}
signed main()
{
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	scanf("%lld%lld", &n, &q);
	for(int i = 1; i < n; i++) {
		int x, y;
		scanf("%lld%lld", &x, &y);
		x += 1; y += 1;
		ver[x].push_back(y);
		ver[y].push_back(x);
	}
	dfs(1, 1);
	build(1, n, 1);
	for(int i = 1; i <= q; i++) {
		int opt, x, l, r;
		scanf("%lld%lld%lld%lld", &opt, &x, &l, &r);
		x += 1;
		if(opt == 1) {
			printf("%lld\n", query(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1));
		} else {
			if(l == r) continue;
			modify(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1);
		}
	}
	return 0;
}
/*
5 10
0 1
0 2
1 3
1 4
1 2 1 5
2 0 6 5
1 3 4 4
2 1 0 6
1 4 8 9
2 1 3 9
1 0 7 9
2 1 7 6
1 4 0 5
1 0 4 6

0
0
0
0
1
3




*/
accuracy: 0.25
time_ms: 120
memory_kb: 108476
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define int long long
#define Mid (l + r >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read() {
	char c; int num, f = 1;
	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
	return f * num;
}
const int N = 2e6 + 1009;
vector<int> ver[N];
int tree[N][11], maxn, lzt[N][11];
int n, q, siz[N], idn[N], tt;
void dfs(int x, int pre) {
	siz[x] = 1;
	idn[x] = ++tt;
	for(auto y : ver[x]) if(y != pre) {
		dfs(y, x);
		siz[x] += siz[y];
	}
}
void update(int rt) {
	for(int i = 0; i < 10; i++) 
		tree[rt][i] = tree[lson][i] + tree[rson][i];
}
void build(int l, int r, int rt) {
	for(int i = 0; i < 10; i++) lzt[rt][i] = i;
	if(l == r) {
		memset(tree[rt], 0, sizeof(tree[rt]));
		tree[rt][0] = 1;
		return ;
	}
	build(l, Mid, lson);
	build(Mid + 1, r, rson);
	update(rt);
}
void mg(int rt, int x, int y) {
//	int tmp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	if(x == y) return ;
	tree[rt][y] += tree[rt][x];
	tree[rt][x] = 0;
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] == x) 
			lzt[rt][i] = y;
//		tmp[lzt[rt][i]] += tree[rt][i];
	}
//	for(int i = 0; i < 10; i++) tree[rt][i] = tmp[i];
}
void pushdown(int rt) {
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] != i) {
			mg(lson, i, lzt[rt][i]);
			mg(rson, i, lzt[rt][i]);
			lzt[rt][i] = i;
		}
	}
}
void modify(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return ;
	if(L <= l && r <= R) {
		mg(rt, x, y);
		return ;
	}
	pushdown(rt);
	if(L <= Mid) modify(l, Mid, L, R, x, y, lson);
	if(Mid <  R) modify(Mid + 1, r, L, R, x, y, rson);
	update(rt);
}
int query(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return 0;
	if(L <= l && r <= R) {
		int cnt = 0;
		for(int i = x; i <= y; i++)	
			cnt += tree[rt][i];
		return cnt;
	}
	pushdown(rt);
	int cnt = 0;
	if(L <= Mid) cnt += query(l, Mid, L, R, x, y, lson);
	if(Mid <  R) cnt += query(Mid + 1, r, L, R, x, y, rson);
	return cnt;
}
signed main()
{
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	scanf("%lld%lld", &n, &q);
	for(int i = 1; i < n; i++) {
		int x, y;
		scanf("%lld%lld", &x, &y);
		x += 1; y += 1;
		ver[x].push_back(y);
		ver[y].push_back(x);
	}
	dfs(1, 1);
	build(1, n, 1);
	for(int i = 1; i <= q; i++) {
		int opt, x, l, r;
		scanf("%lld%lld%lld%lld", &opt, &x, &l, &r);
		x += 1;
		if(opt == 1) {
			printf("%lld\n", query(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1));
		} else {
			if(l == r) continue;
			modify(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1);
		}
	}
	return 0;
}
/*
5 10
0 1
1 2
2 3
3 4
2 2 2 9
2 4 0 7
2 2 7 1
1 0 5 8
2 3 0 2
1 0 2 7
2 4 5 1
1 4 5 6
1 2 5 8
1 0 1 7

0
1
0
0
2


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



*/
accuracy: 0.25
time_ms: 120
memory_kb: 108624
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define int long long
#define Mid (l + r >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read() {
	char c; int num, f = 1;
	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
	return f * num;
}
const int N = 2e6 + 1009;
vector<int> ver[N];
int tree[N][11], maxn, lzt[N][11];
int n, q, siz[N], idn[N], tt;
void dfs(int x, int pre) {
	siz[x] = 1;
	idn[x] = ++tt;
	for(auto y : ver[x]) if(y != pre) {
		dfs(y, x);
		siz[x] += siz[y];
	}
}
void update(int rt) {
//	int tmp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	for(int i = 0; i < 10; i++) {
		tree[rt][i] = tree[lson][i] + tree[rson][i];
//		tmp[lzt[rson][i]] += tree[rson][i];
	}
//	for(int i = 0; i < 10; i++)
//		tree[rt][i] = tmp[i];
}
void build(int l, int r, int rt) {
	for(int i = 0; i < 10; i++) lzt[rt][i] = i;
	if(l == r) {
		memset(tree[rt], 0, sizeof(tree[rt]));
		tree[rt][0] = 1;
		return ;
	}
	build(l, Mid, lson);
	build(Mid + 1, r, rson);
	update(rt);
}
void mg(int rt, int x, int y) {
	int tmp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] == x) 
			lzt[rt][i] = y;
		tmp[lzt[rt][i]] += tree[rt][i];
	}
	for(int i = 0; i < 10; i++) tree[rt][i] = tmp[i];
}
void pushdown(int rt) {
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] != i) {
			mg(lson, i, lzt[rt][i]);
			mg(rson, i, lzt[rt][i]);
			lzt[rt][i] = i;
		}
	}
}
void modify(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return ;
	if(L <= l && r <= R) {
		mg(rt, x, y);
		return ;
	}
	pushdown(rt);
	if(L <= Mid) modify(l, Mid, L, R, x, y, lson);
	if(Mid <  R) modify(Mid + 1, r, L, R, x, y, rson);
	update(rt);
}
int query(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return 0;
	if(L <= l && r <= R) {
		int cnt = 0;
		for(int i = x; i <= y; i++)	
			cnt += tree[rt][i];
		return cnt;
	}
	pushdown(rt);
	int cnt = 0;
	if(L <= Mid) cnt += query(l, Mid, L, R, x, y, lson);
	if(Mid <  R) cnt += query(Mid + 1, r, L, R, x, y, rson);
	return cnt;
}
signed main()
{
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	scanf("%lld%lld", &n, &q);
	for(int i = 1; i < n; i++) {
		int x, y;
		scanf("%lld%lld", &x, &y);
		x += 1; y += 1;
		ver[x].push_back(y);
		ver[y].push_back(x);
	}
	dfs(1, 1);
	build(1, n, 1);
	for(int i = 1; i <= q; i++) {
		int opt, x, l, r;
		scanf("%lld%lld%lld%lld", &opt, &x, &l, &r);
		x += 1;
		if(opt == 1) {
//			cout << idn[x] << " " << idn[x] + siz[x] - 1 << endl;
			printf("%lld\n", query(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1));
		} else {
			if(l == r) continue;
			modify(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1);
		}
	}
	return 0;
}
/*
6 5
0 1
0 2
1 3
1 4
2 5
2 0 0 3
2 5 3 4
1 5 4 4
2 2 4 2
1 2 1 2

*/
accuracy: 0.25
time_ms: 140
memory_kb: 108576
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#define int long long
#define Mid (l + r >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read() {
	char c; int num, f = 1;
	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
	return f * num;
}
const int N = 2e6 + 1009;
vector<int> ver[N];
int tree[N][11], maxn, lzt[N][11];
int n, q, siz[N], idn[N], tt;
void dfs(int x, int pre) {
	siz[x] = 1;
	idn[x] = ++tt;
	for(auto y : ver[x]) if(y != pre) {
		dfs(y, x);
		siz[x] += siz[y];
	}
}
void update(int rt) {
	int tmp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	for(int i = 0; i < 10; i++) {
		tmp[lzt[lson][i]] += tree[lson][i];
		tmp[lzt[rson][i]] += tree[rson][i];
	}
	for(int i = 0; i < 10; i++)
		tree[rt][i] = tmp[i];
}
void build(int l, int r, int rt) {
	for(int i = 0; i < 10; i++) lzt[rt][i] = i;
	if(l == r) {
		memset(tree[rt], 0, sizeof(tree[rt]));
		tree[rt][0] = 1;
		return ;
	}
	build(l, Mid, lson);
	build(Mid + 1, r, rson);
	update(rt);
}
void mg(int rt, int x, int y) {
	int tmp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] == x) { 
			lzt[rt][i] = y;
			tmp[y] += tree[rt][i];
			tree[rt][i] = 0;
		} else {
			tmp[lzt[rt][i]] += tree[rt][i];
		}
	}
	for(int i = 0; i < 10; i++) tree[rt][i] = tmp[i];
}
void pushdown(int rt) {
	for(int i = 0; i < 10; i++) {
		if(lzt[rt][i] != i) {
			mg(lson, i, lzt[rt][i]);
			mg(rson, i, lzt[rt][i]);
			lzt[rt][i] = i;
		}
	}
}
void modify(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return ;
	if(L <= l && r <= R) {
		mg(rt, x, y);
		return ;
	}
	pushdown(rt);
	if(L <= Mid) modify(l, Mid, L, R, x, y, lson);
	if(Mid <  R) modify(Mid + 1, r, L, R, x, y, rson);
	update(rt);
}
int query(int l, int r, int L, int R, int x, int y, int rt) {
	if(l > R || r < L || l > r) return 0;
	if(L <= l && r <= R) {
		int cnt = 0;
		for(int i = x; i <= y; i++)	
			cnt += tree[rt][i];
		return cnt;
	}
	pushdown(rt);
	int cnt = 0;
	if(L <= Mid) cnt += query(l, Mid, L, R, x, y, lson);
	if(Mid <  R) cnt += query(Mid + 1, r, L, R, x, y, rson);
	return cnt;
}
signed main()
{
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	scanf("%lld%lld", &n, &q);
	for(int i = 1; i < n; i++) {
		int x, y;
		scanf("%lld%lld", &x, &y);
		x += 1; y += 1;
		ver[x].push_back(y);
		ver[y].push_back(x);
	}
	dfs(1, 1);
	build(1, n, 1);
	for(int i = 1; i <= q; i++) {
		int opt, x, l, r;
		scanf("%lld%lld%lld%lld", &opt, &x, &l, &r);
		x += 1;
		if(opt == 1) {
//			cout << idn[x] << " " << idn[x] + siz[x] - 1 << endl;
			printf("%lld\n", query(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1));
		} else {
			if(l == r) continue;
			modify(1, n, idn[x], idn[x] + siz[x] - 1, l, r, 1);
		}
	}
	return 0;
}
/*
6 5
0 1
0 2
1 3
1 4
2 5
2 0 0 3
2 5 3 4
1 5 4 4
2 2 4 2
1 2 1 2

*/
accuracy: 0.25
time_ms: 140
memory_kb: 108528
final_rank: 19