【模板】树链剖分

好久不写树剖了,昨天刚好xry提起,今天洛谷智推又有这题....于是就想写一写.....然后果然出现了很多很多的错误2333

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 200010;
int n, m, r, mod, x, y, z, k;
int num, from[MAXN], next[MAXN], to[MAXN], w[MAXN];
int w1[MAXN], a[MAXN << 2], lazy[MAXN << 2];
int son[MAXN], id[MAXN], father[MAXN];
int cnt;
int depth[MAXN];
int size[MAXN], top[MAXN];
int res;
inline int read() {
    char ch; bool f = false; int res = 0;
    while (((ch = getchar()) < '0' || ch > '9') && ch != '-');
    if (ch == '-') f = true; else res = ch - '0';
    while ((ch = getchar()) >= '0' && ch <= '9') res = (res << 3) + (res << 1) + ch - '0';
    return f? ~res + 1 : res;
}
inline void add(int x, int y) { // build tree
	to[++ num] = y, next[num] = from[x], from[x] = num;
	to[++ num] = x, next[num] = from[y], from[y] = num;
}
void dfs1(int x, int fa, int deep) {
	depth[x] = deep;
	father[x] = fa;
	size[x] = 1;
	int maxx = -1; // son 's max
	for (int i = from[x]; i; i = next[i]) {
		int y = to[i];
		if (y == fa) // father
			continue;
		dfs1(y, x, deep + 1);
		size[x] += size[y];
		if (size[y] > maxx) {
			son[x] = y;
			maxx =  size[y];
		}
	}
}
void dfs2(int x, int Top) { // tree link top
	id[x] = ++ cnt; // new number
	w1[cnt] = w[x]; // new value
	top[x] = Top;
	if (! son[x]) // no son
		return;
	dfs2(son[x], Top);
	for (int i = from[x]; i; i = next[i]) {
		int y = to[i];
		if (y == father[x] || y == son[x])
			continue;
		dfs2(y, y); // light son -> link top
	}
}
//segment tree
inline void pushdown(int x, int y) {
	int t = x << 1, w = x << 1 | 1, z = y >> 1;
	lazy[t] += lazy[x], lazy[w] += lazy[x];
	a[t] += lazy[x] * (y - z), a[w] += lazy[x] * z;
	a[t] %= mod, a[w] %= mod, lazy[x] = 0;
}
void build (int x, int t, int w) {
	if (t == w) {
		a[x] = w1[t];
		if (a[x] > mod)
			a[x] %= mod;
		return;
	}
	build(x << 1, t, t + w >> 1); // left son
	build(x << 1 | 1, (t + w >> 1) + 1, w); // right son
	a[x] = (a[x << 1] + a[x << 1 | 1] % mod);
}
void query(int x, int l, int r, int t, int w) {
	if (t <= l && w >= r) {
		res = (res + a[x]) % mod;
		return;
	}
	else {
		int mid = l + r >> 1;
		if (lazy[x])
			pushdown(x, r - l + 1);
		if (t <= mid)
			query(x << 1, l, mid, t, w);
		if (w > mid)
			query(x << 1 | 1, mid + 1, r, t, w);
	}
}
void update(int x, int l, int r, int t, int w, int k) {
	if (t <= l && w >= r)
		lazy[x] += k, a[x] += k * (r - l + 1);
	else {
		int mid = l + r >> 1;
		if (lazy[x])
			pushdown(x, r - l + 1);
		if (t <= mid)
			update(x << 1, l, mid, t, w, k);
		if (w > mid)
			update(x << 1 | 1, mid + 1, r, t, w, k);
		a[x] = (a[x << 1] + a[x << 1 | 1]) % mod;
	}
}
//
inline void addroad(int x, int y, int k) {
	k %= mod;
	while (top[x] != top[y]) { 
		if (depth[top[x]] < depth[top[y]])
			swap(x, y);
		update(1, 1, n, id[top[x]], id[x], k);
		x = father[top[x]];
	}
	if (depth[x] > depth[y])
		swap(x, y);
	update(1, 1, n, id[x], id[y], k);
}
inline int sumroad(int x, int y) {
	int ans = 0;
	while (top[x] != top[y]) {
		if (depth[top[x]] < depth[top[y]])
			swap(x, y);
		res = 0;
		query(1, 1, n, id[top[x]], id[x]);
		ans = (ans + res) % mod;
		x = father[top[x]];
	}
	if (depth[x] > depth[y])
		swap(x, y);
	res = 0;
	query(1, 1, n, id[x], id[y]);
	ans = ans + res;
	return ans % mod;
}
inline int sumson(int x) {
	res = 0;
	query(1, 1, n, id[x], id[x] + size[x] - 1);
	return res;
}
inline void addson(int x,int k) {
	update(1, 1, n, id[x], id[x] + size[x] - 1, k);
}
int main() {
	n = read(), m = read(), r = read(), mod = read();
	for (int i = 1; i <= n; i ++)
		w[i]=read();
	for (int i = 1; i < n; i ++)
		add(read(), read());
	dfs1(r, 0, 1);
	dfs2(r, r);
	build(1, 1, n);
	while (m --) {
		k = read(), x = read();
		if (k == 1) {
			y = read(), z=read();
			addroad(x, y, z);
		}
		else if (k == 2) {
			y = read();
			printf("%d\n", sumroad(x, y));
		}
		else if (k == 3) {
			y = read();
			addson(x, y);
		}
		else printf("%d\n", sumson(x));
	}
	return 0;
}

  

posted @ 2019-03-21 10:38  Trimsteanima  阅读(148)  评论(0编辑  收藏  举报
Live2D