列表

详情


NC243739. Forest of Magic

描述

English Statement (PDF)
中文题面 (PDF)

输入描述

见 PDF 题面

输出描述

见 PDF 题面

示例1

输入:

3 5
1 2
1 3
2 2 3 1 4
3 1 1
1 13
2 13 8 14 13
3 13 14

输出:

12
14

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 2551ms, 内存消耗: 181040K, 提交时间: 2022-09-24 11:52:59

#include <bits/stdc++.h>

using namespace std;

constexpr int maxn = 200005;

struct lct_node {
	lct_node *ch[2], *p;
	int self_size, tree_size;

	lct_node() : self_size(1), tree_size(1) {}

	void update() {
		tree_size = self_size + ch[0] -> tree_size + ch[1] -> tree_size;
	}
} lct_null[maxn];

void lct_init(lct_node *x) {
	*x = lct_node();
	x -> ch[0] = x -> ch[1] = x -> p = lct_null;
}

inline bool isroot(lct_node *x) {
	return x != x -> p -> ch[0] && x != x -> p -> ch[1];
}

inline int dir(lct_node *x) {
	return x == x -> p -> ch[1];
}

void lct_rotate(lct_node *x, int d) {
	lct_node *y = x -> ch[d ^ 1];

	y -> p = x -> p;
	if (!isroot(x))
		x -> p -> ch[dir(x)] = y;
	
	if ((x -> ch[d ^ 1] = y -> ch[d]) != lct_null)
		y -> ch[d] -> p = x;
	(y -> ch[d] = x) -> p = y;

	x -> update();
	y -> update();
}

void lct_splay(lct_node *x) {
	while (!isroot(x)) {
		if (isroot(x -> p)) {
			lct_rotate(x -> p, dir(x) ^ 1);
			break;
		}

		if (dir(x) == dir(x -> p))
			lct_rotate(x -> p -> p, dir(x -> p) ^ 1);
		else
			lct_rotate(x -> p, dir(x) ^ 1);
		lct_rotate(x -> p, dir(x) ^ 1);
	}
}

lct_node *lct_access(lct_node *x) {
	lct_node *y = lct_null;

	while (x != lct_null) {
		lct_splay(x);

		x -> self_size += x -> ch[1] -> tree_size;
		x -> self_size -= y -> tree_size;
		x -> ch[1] = y;
		(y = x) -> update();

		x = x -> p;
	}

	return y;
}

void lct_link(lct_node *x, lct_node *y) {
	lct_access(y);
	lct_splay(y);
	x -> p = y;
	y -> self_size += x -> tree_size;
	y -> tree_size += x -> tree_size;
}

int lct_query(lct_node *x) {
	lct_access(x);
	return x -> self_size;
}

pair<long long, long long> operator + (const pair<long long, long long> &a, const pair<long long, long long> &b) {
	return {a.first + b.first, a.second + b.second};
}

pair<long long, long long> &operator += (pair<long long, long long> &a, const pair<long long, long long> &b) {
	a.first += b.first;
	a.second += b.second;
	return a;
}

mt19937 rng(233);

struct sbt_node {
	int key, size;
	pair<long long, long long> val, sum;
	sbt_node *ch[2];

	sbt_node(int key, const pair<long long, long long> &val) : key(key), size(1),
		val(val), sum(val) {}

	void update() {
		size = 1 + ch[0] -> size + ch[1] -> size;
		sum = val + ch[0] -> sum + ch[1] -> sum;
	}
} *sbt_null = new sbt_node(0, {0, 0});

sbt_node *new_sbt_node(int key, const pair<long long, long long> &val) {
	sbt_node *x = new sbt_node(key, val);
	x -> ch[0] = x -> ch[1] = sbt_null;
	return x;
}

void sbt_rotate(sbt_node *&x, int d) {
	sbt_node *y = x -> ch[d ^ 1];
	x -> ch[d ^ 1] = y -> ch[d];
	y -> ch[d] = x;
	x -> update();
	(x = y) -> update();
}

void sbt_maintain(sbt_node *&x, int d) {
	if (x -> ch[d] -> ch[d] -> size > x -> ch[d ^ 1] -> size)
		sbt_rotate(x, d ^ 1);
	else if (x -> ch[d] -> ch[d ^ 1] -> size > x -> ch[d ^ 1] -> size) {
		sbt_rotate(x -> ch[d], d);
		sbt_rotate(x, d ^ 1);
	}
	else
		return;
	
	sbt_maintain(x -> ch[0], 0);
	sbt_maintain(x -> ch[1], 1);
	sbt_maintain(x, 0);
	sbt_maintain(x, 1);
}

void sbt_insert(sbt_node *&x, int k, const pair<long long, long long> &v) {
	if (x == sbt_null) {
		x = new_sbt_node(k, v);
		return;
	}
	
	if (k == x -> key) {
		x -> val += v;
		x -> sum += v;
		return;
	}

	int d = (k > x -> key);
	sbt_insert(x -> ch[d], k, v);
	x -> update();
	sbt_maintain(x, d);
}

void sbt_travel(sbt_node *x, vector<pair<int, pair<long long, long long> > > &vec) {
	if (x == sbt_null)
		return;

	sbt_travel(x -> ch[0], vec);
	vec.emplace_back(x -> key, x -> val);
	sbt_travel(x -> ch[1], vec);
}

void sbt_destroy(sbt_node *&x) {
	if (x == sbt_null)
		return;
	
	sbt_destroy(x -> ch[0]);
	sbt_destroy(x -> ch[1]);
	delete x;
	x = sbt_null;
}

void sbt_build(sbt_node *&x, int l, int r, const vector<pair<int, pair<long long, long long> > > &vec) {
	if (l > r) {
		x = sbt_null;
		return;
	}

	int mid = (l + r) / 2;

	x = new_sbt_node(vec[mid].first, vec[mid].second);

	sbt_build(x -> ch[0], l, mid - 1, vec);
	sbt_build(x -> ch[1], mid + 1, r, vec);

	x -> update();
}

pair<long long, long long> sbt_query(const sbt_node *x, int k) {
	if (x == sbt_null)
		return {0, 0ll};
	
	if (k <= x -> key) {
		auto ans = sbt_query(x -> ch[0], k);
		if (k == x -> key)
			ans += x -> val;
		
		return ans;
	}
	else
		return x -> val + x -> ch[0] -> sum + sbt_query(x -> ch[1], k);
}

struct treap_node {
	int size, weight;
	sbt_node *self_root, *tree_root;

	treap_node *ch[2], *p;

	treap_node() : size(1), weight(0), self_root(sbt_null), tree_root(sbt_null) {}

	void update() {
		size = 1 + ch[0] -> size + ch[1] -> size;
		weight = self_root -> size + ch[0] -> weight + ch[1] -> weight;
	}
} *treap_null = new treap_node(), *treap_root = treap_null;

treap_node *new_treap_node() {
	treap_node *x = new treap_node();
	x -> ch[0] = x -> ch[1] = x -> p = treap_null;
	return x;
}

void treap_travel(treap_node *x, vector<treap_node*> &vec) {
	if (x == treap_null)
		return;

	// cerr << "x = " << x << ", size = " << x -> size << endl;
	
	treap_travel(x -> ch[0], vec);

	vec.push_back(x);
	sbt_destroy(x -> tree_root);

	treap_travel(x -> ch[1], vec);
}

vector<pair<int, pair<long long, long long> > > vector_merge(const vector<pair<int, pair<long long, long long> > > &a, const vector<pair<int, pair<long long, long long> > > &b) {
	vector<pair<int, pair<long long, long long> > > c;
	c.reserve(a.size() + b.size());

	auto i = a.begin(), j = b.begin();
	while (i != a.end() && j != b.end()) {
		if (i -> first < j -> first)
			c.push_back(*i++);
		else if (i -> first > j -> first)
			c.push_back(*j++);
		else {
			c.push_back(make_pair(i -> first, i -> second + j -> second));
			i++;
			j++;
		}
	}

	while (i != a.end())
		c.push_back(*i++);
	while (j != b.end())
		c.push_back(*j++);

	return c;
}

vector<pair<int, pair<long long, long long> > > treap_rebuild(treap_node *&x, int l, int r, vector<treap_node*> &vec) {
	if (l > r) {
		x = treap_null;
		return {};
	}
	
	int mid = (l + r) / 2;
	x = vec[mid];

	auto u = move(treap_rebuild(x -> ch[0], l, mid - 1, vec));
	if (x -> ch[0] != treap_null)
		x -> ch[0] -> p = x;
	
	auto v = move(treap_rebuild(x -> ch[1], mid + 1, r, vec));
	if (x -> ch[1] != treap_null)
		x -> ch[1] -> p = x;
	
	vector<pair<int, pair<long long, long long> > > vt;
	sbt_travel(x -> self_root, vt);
	
	auto res = vector_merge(vector_merge(u, v), vt);
	sbt_build(x -> tree_root, 0, (int)res.size() - 1, res);
	
	x -> update();
	// cerr << "now x(" << x << ") -> size = " << x -> size << endl;

	return res;
}

int treap_rank(treap_node *x) { // 1-based
	if (x == treap_null)
		return 0;

	int ans = x -> ch[0] -> size + 1;

	while (x -> p != treap_null) {
		if (x == x -> p -> ch[1])
			ans += x -> p -> ch[0] -> size + 1;
		
		x = x -> p;
	}

	return ans;
}

treap_node *treap_find(int k, treap_node *x = treap_root) {
	while (x != treap_null) {
		if (k == x -> ch[0] -> size + 1)
			return x;
		
		int d = (k > x -> ch[0] -> size + 1);
		if (d)
			k -= x -> ch[0] -> size + 1;
		
		x = x -> ch[d];
	}
	
	assert(false);
	return nullptr;
}

void treap_insert(treap_node *x, treap_node *o) { // after o
	if (o -> ch[1] == treap_null) {
		o -> ch[1] = x;
		x -> p = o;
	}
	else {
		o = o -> ch[1];
		while (o -> ch[0] != treap_null)
			o = o -> ch[0];

		o -> ch[0] = x;
		x -> p = o;
	}

	treap_node *goat = treap_null;
	while (o != treap_null) {
		o -> update();

		if ((int)(rng() % (o -> size + o -> weight)) < (x -> size + x -> weight))
			goat = o;
		o = o -> p;
	}
	
	if (goat == treap_null)
		return;

	// cerr << "goat = " << goat << endl;
	
	vector<treap_node*> vec;
	treap_travel(goat, vec);
	// cerr << "vec.size() = " << vec.size() << endl;

	// cerr << "root = " << treap_root << endl;
	if (goat == treap_root) {
		treap_rebuild(treap_root, 0, (int)vec.size() - 1, vec);
		treap_root -> p = treap_null;
		// cerr << "root = " << treap_root << endl;
	}
	else {
		// assert(goat -> p != treap_null);
		treap_node *p = goat -> p;
		int d = (goat == p -> ch[1]);
		treap_rebuild(p -> ch[d], 0, (int)vec.size() - 1, vec);
		p -> ch[d] -> p = p;
	}
}

void treap_modify(treap_node *x, int key, const pair<long long, long long> &val) {
	sbt_insert(x -> self_root, key, val);

	while (x != treap_null) {
		sbt_insert(x -> tree_root, key, val);
		x = x -> p;
	}
}

pair<long long, long long> treap_query(treap_node *x, int l, int r, int key) { // 1-based
	if (x == treap_null)
		return {0, 0ll};
	
	if (l == 1 && r == x -> size)
		return sbt_query(x -> tree_root, key);
	
	int mid = x -> ch[0] -> size + 1;
	
	// cerr << "x = " << x << ", l = " << l << ", r = " << r << ", mid = " << mid << endl;
	
	pair<long long, long long> ans(0, 0ll);
	if (l <= mid && r >= mid)
		ans = sbt_query(x -> self_root, key);
	
	if (l < mid)
		ans += treap_query(x -> ch[0], l, min(mid - 1, r), key);
	if (r > mid)
		ans += treap_query(x -> ch[1], max(1, l - mid), r - mid, key);
	
	return ans;
}

vector<int> G[maxn];
int pr[maxn], d[maxn], f[19][maxn];
int dfn[maxn], tim, id[maxn];
treap_node *treap_id[maxn];

void treap_build(treap_node *&o, int l, int r) {
	if (l > r) {
		o = treap_null;
		return;
	}
	
	int mid = rng() % (r - l + 1) + l;
	treap_id[id[mid]] = o = new treap_node();

	treap_build(o -> ch[0], l, mid - 1);
	if (o -> ch[0] != treap_null)
		o -> ch[0] -> p = o;
	
	treap_build(o -> ch[1], mid + 1, r);
	if (o -> ch[1] != treap_null)
		o -> ch[1] -> p = o;
	
	o -> update();
	// cerr << "o = " << o << "  size = " << o -> size << endl;
}

void dfs(int x) {
	dfn[x] = ++tim;
	id[tim] = x;
	d[x] = d[pr[x]] + 1;

	for (int y : G[x])
		if (y != pr[x]) {
			pr[y] = x;

			dfs(y);

			lct_null[y].p = lct_null + x;
			lct_null[x].self_size += lct_null[y].tree_size;
		}
	
	lct_null[x].tree_size = lct_null[x].self_size;
}

int lca(int x, int y) {
	if (d[x] != d[y]) {
		if (d[x] < d[y])
			swap(x, y);
		
		int t = d[x] - d[y];
		for (int i = 0; i < 19; i++)
			if (t >> i & 1)
				x = f[i][x];
	}
	if (x == y)
		return x;
	
	for (int i = 18; ~i; i--)
		if (f[i][x] != f[i][y]) {
			x = f[i][x];
			y = f[i][y];
		}
	
	return f[0][x];
}

int main() {

	lct_null -> ch[0] = lct_null -> ch[1] = lct_null -> p = lct_null;
	lct_null -> self_size = lct_null -> tree_size = 0;
	treap_null -> ch[0] = treap_null -> ch[1] = treap_null -> p = treap_null;
	treap_null -> size = 0;
	sbt_null -> ch[0] = sbt_null -> ch[1] = sbt_null;
	sbt_null -> size = 0;

	int n, m;
	scanf("%d%d", &n, &m);

	for (int i = 1; i <= n; i++)
		lct_init(lct_null + i);

	for (int i = 1; i < n; i++) {
		int x, y;
		scanf("%d%d", &x, &y);

		G[x].push_back(y);
		G[y].push_back(x);
	}

	dfs(1);

	for (int i = 1; i <= n; i++)
		f[0][i] = pr[i];
	
	for (int j = 1; j < 19; j++)
		for (int i = 1; i <= n; i++)
			f[j][i] = f[j - 1][f[j - 1][i]];
	
	treap_build(treap_root, 1, n);
	treap_root -> p = treap_null;

	int last = 0;

	while (m--) {
		int op;
		scanf("%d", &op);

		if (op == 1) {
			scanf("%d", &pr[++n]);
			pr[n] ^= last;

			d[n] = d[pr[n]] + 1;
			f[0][n] = pr[n];
			for (int j = 1; j < 19; j++)
				f[j][n] = f[j - 1][f[j - 1][n]];
			
			treap_id[n] = new treap_node();
			treap_id[n] -> ch[0] = treap_id[n] -> ch[1] = treap_id[n] -> p = treap_null;
			treap_node *last = treap_find(treap_rank(treap_id[pr[n]]) + lct_query(lct_null + pr[n]) - 1);
			treap_insert(treap_id[n], last);

			lct_init(lct_null + n);
			lct_link(lct_null + n, lct_null + pr[n]);

			// cerr << "--- now ---" << endl;
			// for (int i = 1; i <= n; i++)
			// 	cerr << "i = " << i << "  rank = " << treap_rank(treap_id[i]) << endl;
		}
		else if (op == 2) {
			int x, y, c, k;
			scanf("%d%d%d%d", &x, &y, &c, &k);
			x ^= last;
			y ^= last;
			c ^= last;
			k ^= last;

			int z = lca(x, y);
			// cerr << "x = " << x << "  y = " << y << "  z = " << z << endl;
			treap_modify(treap_id[x], c, {-k, (long long)k * (d[x] + 1)});
			treap_modify(treap_id[y], c, {-k, (long long)k * (d[y] + 1)});
			treap_modify(treap_id[z], c, {2 * k, -k * (long long)(d[x] + d[y] + 2) + (long long)k * (d[x] + d[y] - 2 * d[z] + 1)});
		}
		else {
			int x, c;
			scanf("%d%d", &x, &c);
			x ^= last;
			c ^= last;

			int l = treap_rank(treap_id[x]), r = l + lct_query(lct_null + x) - 1;
			// cerr << "l = " << l << "  r = " << r << endl;
			auto [a, b] = treap_query(treap_root, l, r, c);
			long long ans = a * d[x] + b;
			// cerr << "a = " << a << "  b = " << b << endl;

			printf("%lld\n", ans);

			last = ans & 2147483647;
		}
	}

	return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 1908ms, 内存消耗: 120180K, 提交时间: 2022-09-23 22:33:33

#include <bits/stdc++.h>

using namespace std;

constexpr int maxn = 200005;
constexpr double alpha = 0.75;

struct lct_node {
	lct_node *ch[2], *p;
	int self_size, tree_size;

	lct_node() : self_size(1), tree_size(1) {}

	void update() {
		tree_size = self_size + ch[0] -> tree_size + ch[1] -> tree_size;
	}
} lct_null[maxn];

void lct_init(lct_node *x) {
	*x = lct_node();
	x -> ch[0] = x -> ch[1] = x -> p = lct_null;
}

inline bool isroot(lct_node *x) {
	return x != x -> p -> ch[0] && x != x -> p -> ch[1];
}

inline int dir(lct_node *x) {
	return x == x -> p -> ch[1];
}

void lct_rotate(lct_node *x, int d) {
	lct_node *y = x -> ch[d ^ 1];

	y -> p = x -> p;
	if (!isroot(x))
		x -> p -> ch[dir(x)] = y;
	
	if ((x -> ch[d ^ 1] = y -> ch[d]) != lct_null)
		y -> ch[d] -> p = x;
	(y -> ch[d] = x) -> p = y;

	x -> update();
	y -> update();
}

void lct_splay(lct_node *x) {
	while (!isroot(x)) {
		if (isroot(x -> p)) {
			lct_rotate(x -> p, dir(x) ^ 1);
			break;
		}

		if (dir(x) == dir(x -> p))
			lct_rotate(x -> p -> p, dir(x -> p) ^ 1);
		else
			lct_rotate(x -> p, dir(x) ^ 1);
		lct_rotate(x -> p, dir(x) ^ 1);
	}
}

lct_node *lct_access(lct_node *x) {
	lct_node *y = lct_null;

	while (x != lct_null) {
		lct_splay(x);

		x -> self_size += x -> ch[1] -> tree_size;
		x -> self_size -= y -> tree_size;
		x -> ch[1] = y;
		(y = x) -> update();

		x = x -> p;
	}

	return y;
}

void lct_link(lct_node *x, lct_node *y) {
	lct_access(y);
	lct_splay(y);
	x -> p = y;
	y -> self_size += x -> tree_size;
	y -> tree_size += x -> tree_size;
}

int lct_query(lct_node *x) {
	lct_access(x);
	return x -> self_size;
}

pair<long long, long long> operator + (const pair<long long, long long> &a, const pair<long long, long long> &b) {
	return {a.first + b.first, a.second + b.second};
}

pair<long long, long long> &operator += (pair<long long, long long> &a, const pair<long long, long long> &b) {
	a.first += b.first;
	a.second += b.second;
	return a;
}

struct sbt_node {
	int key, size;
	pair<long long, long long> val, sum;
	sbt_node *ch[2];

	sbt_node(int key, const pair<long long, long long> &val) : key(key), size(1),
		val(val), sum(val) {}

	void update() {
		size = 1 + ch[0] -> size + ch[1] -> size;
		sum = val + ch[0] -> sum + ch[1] -> sum;
	}
} *sbt_null = new sbt_node(0, {0, 0});

sbt_node *new_sbt_node(int key, const pair<long long, long long> &val) {
	sbt_node *x = new sbt_node(key, val);
	x -> ch[0] = x -> ch[1] = sbt_null;
	return x;
}

void sbt_rotate(sbt_node *&x, int d) {
	sbt_node *y = x -> ch[d ^ 1];
	x -> ch[d ^ 1] = y -> ch[d];
	y -> ch[d] = x;
	x -> update();
	(x = y) -> update();
}

void sbt_maintain(sbt_node *&x, int d) {
	if (x -> ch[d] -> ch[d] -> size > x -> ch[d ^ 1] -> size)
		sbt_rotate(x, d ^ 1);
	else if (x -> ch[d] -> ch[d ^ 1] -> size > x -> ch[d ^ 1] -> size) {
		sbt_rotate(x -> ch[d], d);
		sbt_rotate(x, d ^ 1);
	}
	else
		return;
	
	sbt_maintain(x -> ch[0], 0);
	sbt_maintain(x -> ch[1], 1);
	sbt_maintain(x, 0);
	sbt_maintain(x, 1);
}

void sbt_insert(sbt_node *&x, int k, const pair<long long, long long> &v) {
	if (x == sbt_null) {
		x = new_sbt_node(k, v);
		return;
	}
	
	if (k == x -> key) {
		x -> val += v;
		x -> sum += v;
		return;
	}

	int d = (k > x -> key);
	sbt_insert(x -> ch[d], k, v);
	x -> update();
	sbt_maintain(x, d);
}

void sbt_travel(sbt_node *x, vector<pair<int, pair<long long, long long> > > &vec) {
	if (x == sbt_null)
		return;

	sbt_travel(x -> ch[0], vec);
	vec.emplace_back(x -> key, x -> val);
	sbt_travel(x -> ch[1], vec);
}

void sbt_destroy(sbt_node *&x) {
	if (x == sbt_null)
		return;
	
	sbt_destroy(x -> ch[0]);
	sbt_destroy(x -> ch[1]);
	delete x;
	x = sbt_null;
}

void sbt_build(sbt_node *&x, int l, int r, const vector<pair<int, pair<long long, long long> > > &vec) {
	if (l > r) {
		x = sbt_null;
		return;
	}

	int mid = (l + r) / 2;

	x = new_sbt_node(vec[mid].first, vec[mid].second);

	sbt_build(x -> ch[0], l, mid - 1, vec);
	sbt_build(x -> ch[1], mid + 1, r, vec);

	x -> update();
}

pair<long long, long long> sbt_query(const sbt_node *x, int k) {
	if (x == sbt_null)
		return {0, 0ll};
	
	if (k <= x -> key) {
		auto ans = sbt_query(x -> ch[0], k);
		if (k == x -> key)
			ans += x -> val;
		
		return ans;
	}
	else
		return x -> val + x -> ch[0] -> sum + sbt_query(x -> ch[1], k);
}

struct treap_node {
	int size, weight;
	sbt_node *self_root, *tree_root;

	treap_node *ch[2], *p;

	treap_node() : size(1), weight(0), self_root(sbt_null), tree_root(sbt_null) {}

	void update() {
		size = 1 + ch[0] -> size + ch[1] -> size;
		weight = self_root -> size + ch[0] -> weight + ch[1] -> weight;
	}
} *treap_null = new treap_node(), *treap_root = treap_null;

treap_node *new_treap_node() {
	treap_node *x = new treap_node();
	x -> ch[0] = x -> ch[1] = x -> p = treap_null;
	return x;
}

void treap_travel(treap_node *x, vector<treap_node*> &vec) {
	if (x == treap_null)
		return;
	
	treap_travel(x -> ch[0], vec);

	vec.push_back(x);
	sbt_destroy(x -> tree_root);

	treap_travel(x -> ch[1], vec);
}

vector<pair<int, pair<long long, long long> > > vector_merge(const vector<pair<int, pair<long long, long long> > > &a, const vector<pair<int, pair<long long, long long> > > &b) {
	vector<pair<int, pair<long long, long long> > > c;
	c.reserve(a.size() + b.size());

	auto i = a.begin(), j = b.begin();
	while (i != a.end() && j != b.end()) {
		if (i -> first < j -> first)
			c.push_back(*i++);
		else if (i -> first > j -> first)
			c.push_back(*j++);
		else {
			c.push_back(make_pair(i -> first, i -> second + j -> second));
			i++;
			j++;
		}
	}

	while (i != a.end())
		c.push_back(*i++);
	while (j != b.end())
		c.push_back(*j++);

	return c;
}

vector<pair<int, pair<long long, long long> > > treap_rebuild(treap_node *&x, int l, int r, vector<treap_node*> &vec) {
	if (l > r) {
		x = treap_null;
		return {};
	}

	int tmp = 1e9, left = 0, right = 0;
	for (int i = l; i <= r; i++)
		right += vec[i] -> self_root -> size + 1;
	
	int mid = -1;
	for (int i = l; i <= r; i++) {
		right -= vec[i] -> self_root -> size + 1;
		int val = max(left, right);

		if (val < tmp) {
			tmp = val;
			mid = i;
		}

		left += vec[i] -> self_root -> size + 1;
	}
	assert(mid >= 0);

	x = vec[mid];

	auto u = move(treap_rebuild(x -> ch[0], l, mid - 1, vec));
	if (x -> ch[0] != treap_null)
		x -> ch[0] -> p = x;
	
	auto v = move(treap_rebuild(x -> ch[1], mid + 1, r, vec));
	if (x -> ch[1] != treap_null)
		x -> ch[1] -> p = x;
	
	vector<pair<int, pair<long long, long long> > > vt;
	sbt_travel(x -> self_root, vt);
	
	auto res = vector_merge(vector_merge(u, v), vt);
	sbt_build(x -> tree_root, 0, (int)res.size() - 1, res);
	
	x -> update();

	return res;
}

int treap_rank(treap_node *x) { // 1-based
	if (x == treap_null)
		return 0;

	int ans = x -> ch[0] -> size + 1;

	while (x -> p != treap_null) {
		if (x == x -> p -> ch[1])
			ans += x -> p -> ch[0] -> size + 1;
		
		x = x -> p;
	}

	return ans;
}

treap_node *treap_find(int k, treap_node *x = treap_root) {
	while (x != treap_null) {
		if (k == x -> ch[0] -> size + 1)
			return x;
		
		int d = (k > x -> ch[0] -> size + 1);
		if (d)
			k -= x -> ch[0] -> size + 1;
		
		x = x -> ch[d];
	}
	
	assert(false);
	return nullptr;
}

void treap_insert(treap_node *x, treap_node *o) { // after o
	if (o -> ch[1] == treap_null) {
		o -> ch[1] = x;
		x -> p = o;
	}
	else {
		o = o -> ch[1];
		while (o -> ch[0] != treap_null)
			o = o -> ch[0];

		o -> ch[0] = x;
		x -> p = o;
	}

	treap_node *goat = treap_null;
	while (o != treap_null) {
		o -> update();

		if (max(o -> ch[0] -> weight + o -> ch[0] -> size, o -> ch[1] -> weight + o -> ch[1] -> size) > (o -> weight + o -> size) * alpha + 5)
			goat = o;

		o = o -> p;
	}
	
	if (goat == treap_null)
		return;
	
	vector<treap_node*> vec;
	treap_travel(goat, vec);

	if (goat == treap_root) {
		treap_rebuild(treap_root, 0, (int)vec.size() - 1, vec);
		treap_root -> p = treap_null;
	}
	else {
		treap_node *p = goat -> p;
		int d = (goat == p -> ch[1]);
		treap_rebuild(p -> ch[d], 0, (int)vec.size() - 1, vec);
		p -> ch[d] -> p = p;
	}
}

void treap_modify(treap_node *x, int key, const pair<long long, long long> &val) {
	sbt_insert(x -> self_root, key, val);

	while (x != treap_null) {
		sbt_insert(x -> tree_root, key, val);
		x = x -> p;
	}
}

pair<long long, long long> treap_query(treap_node *x, int l, int r, int key) { // 1-based
	if (x == treap_null)
		return {0, 0ll};
	
	if (l == 1 && r == x -> size)
		return sbt_query(x -> tree_root, key);
	
	int mid = x -> ch[0] -> size + 1;
	
	pair<long long, long long> ans(0, 0ll);
	if (l <= mid && r >= mid)
		ans = sbt_query(x -> self_root, key);
	
	if (l < mid)
		ans += treap_query(x -> ch[0], l, min(mid - 1, r), key);
	if (r > mid)
		ans += treap_query(x -> ch[1], max(1, l - mid), r - mid, key);
	
	return ans;
}

vector<int> G[maxn];
int pr[maxn], d[maxn], f[19][maxn];
int dfn[maxn], tim, id[maxn];
treap_node *treap_id[maxn];

void treap_build(treap_node *&o, int l, int r) {
	if (l > r) {
		o = treap_null;
		return;
	}
	
	int mid = (l + r) / 2;
	treap_id[id[mid]] = o = new treap_node();

	treap_build(o -> ch[0], l, mid - 1);
	if (o -> ch[0] != treap_null)
		o -> ch[0] -> p = o;
	
	treap_build(o -> ch[1], mid + 1, r);
	if (o -> ch[1] != treap_null)
		o -> ch[1] -> p = o;
	
	o -> update();
}

void dfs(int x) {
	dfn[x] = ++tim;
	id[tim] = x;
	d[x] = d[pr[x]] + 1;

	for (int y : G[x])
		if (y != pr[x]) {
			pr[y] = x;

			dfs(y);

			lct_null[y].p = lct_null + x;
			lct_null[x].self_size += lct_null[y].tree_size;
		}
	
	lct_null[x].tree_size = lct_null[x].self_size;
}

int lca(int x, int y) {
	if (d[x] != d[y]) {
		if (d[x] < d[y])
			swap(x, y);
		
		int t = d[x] - d[y];
		for (int i = 0; i < 19; i++)
			if (t >> i & 1)
				x = f[i][x];
	}
	if (x == y)
		return x;
	
	for (int i = 18; ~i; i--)
		if (f[i][x] != f[i][y]) {
			x = f[i][x];
			y = f[i][y];
		}
	
	return f[0][x];
}

int main() {

	lct_null -> ch[0] = lct_null -> ch[1] = lct_null -> p = lct_null;
	lct_null -> self_size = lct_null -> tree_size = 0;
	treap_null -> ch[0] = treap_null -> ch[1] = treap_null -> p = treap_null;
	treap_null -> size = 0;
	sbt_null -> ch[0] = sbt_null -> ch[1] = sbt_null;
	sbt_null -> size = 0;

	int n, m;
	scanf("%d%d", &n, &m);

	for (int i = 1; i <= n; i++)
		lct_init(lct_null + i);

	for (int i = 1; i < n; i++) {
		int x, y;
		scanf("%d%d", &x, &y);

		G[x].push_back(y);
		G[y].push_back(x);
	}

	dfs(1);

	for (int i = 1; i <= n; i++)
		f[0][i] = pr[i];
	
	for (int j = 1; j < 19; j++)
		for (int i = 1; i <= n; i++)
			f[j][i] = f[j - 1][f[j - 1][i]];
	
	treap_build(treap_root, 1, n);
	treap_root -> p = treap_null;

	int last = 0;

	while (m--) {
		int op;
		scanf("%d", &op);

		if (op == 1) {
			scanf("%d", &pr[++n]);
			pr[n] ^= last;

			d[n] = d[pr[n]] + 1;
			f[0][n] = pr[n];
			for (int j = 1; j < 19; j++)
				f[j][n] = f[j - 1][f[j - 1][n]];
			
			treap_id[n] = new treap_node();
			treap_id[n] -> ch[0] = treap_id[n] -> ch[1] = treap_id[n] -> p = treap_null;
			treap_node *last = treap_find(treap_rank(treap_id[pr[n]]) + lct_query(lct_null + pr[n]) - 1);
			treap_insert(treap_id[n], last);

			lct_init(lct_null + n);
			lct_link(lct_null + n, lct_null + pr[n]);
		}
		else if (op == 2) {
			int x, y, c, k;
			scanf("%d%d%d%d", &x, &y, &c, &k);
			x ^= last;
			y ^= last;
			c ^= last;
			k ^= last;

			int z = lca(x, y);
			treap_modify(treap_id[x], c, {-k, (long long)k * (d[x] + 1)});
			treap_modify(treap_id[y], c, {-k, (long long)k * (d[y] + 1)});
			treap_modify(treap_id[z], c, {2 * k, -k * (long long)(d[x] + d[y] + 2) + (long long)k * (d[x] + d[y] - 2 * d[z] + 1)});
		}
		else {
			int x, c;
			scanf("%d%d", &x, &c);
			x ^= last;
			c ^= last;

			int l = treap_rank(treap_id[x]), r = l + lct_query(lct_null + x) - 1;
			auto [a, b] = treap_query(treap_root, l, r, c);
			long long ans = a * d[x] + b;

			printf("%lld\n", ans);

			last = ans & 2147483647;
		}
	}

	return 0;
}

上一题