树链剖分之重链剖分 模板

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010
#define ll long long
int P;
int a[N];
int last[N], nxt[N * 2], to[N * 2], len = 0;
int si[N], hv[N], fa[N], dp[N], dfn[N], tp[N];
ll f[N * 4], bz[N * 4];
void add(int x, int y) {
	to[++len] = y;
	nxt[len] = last[x];
	last[x] = len;
}
void dfs0(int k) {
	si[k] = 1, dp[k] = dp[fa[k]] + 1;
	for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa[k]) {
		fa[to[i]] = k;
		dfs0(to[i]);
		si[k] += si[to[i]];
		if(si[to[i]] > si[hv[k]]) hv[k] = to[i];
	}
}
void dfs(int k, int rt) {
	dfn[k] = ++dfn[0];
	tp[k] = rt;
	if(hv[k]) dfs(hv[k], rt);
	for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa[k] && to[i] != hv[k]) dfs(to[i], to[i]);
}
void down(int v, int l, int r, int mid) {
	f[v * 2] = (f[v * 2] + bz[v] * (mid - l + 1)) % P;
	f[v * 2 + 1] = (f[v * 2 + 1] + bz[v] * (r - mid)) % P;
	bz[v * 2] = (bz[v * 2] + bz[v]) % P;
	bz[v * 2 + 1] = (bz[v * 2 + 1] + bz[v]) % P;
	bz[v] = 0;
}
void ins(int v, int l, int r, int x, int y, ll c) {
	if(x <= l && r <= y) {
		f[v] = (f[v] + c * (r - l + 1)) % P;
		bz[v] = (bz[v] + c) % P;
	}
	else {
		int mid = (l + r) / 2;
		down(v, l, r, mid);
		if(x <= mid) ins(v * 2, l, mid, x, y, c);
		if(y > mid) ins(v * 2 + 1, mid + 1, r, x, y, c);
		f[v] = (f[v * 2] + f[v * 2 + 1]) % P;
	}
}
ll find(int v, int l, int r, int x, int y) {
	if(x <= l && r <= y) return f[v];
	int mid = (l + r) / 2;
	down(v, l, r, mid);
	ll s = 0;
	if(x <= mid) s = (s + find(v * 2, l, mid, x, y)) % P;
	if(y > mid) s = (s + find(v * 2 + 1, mid + 1, r, x, y)) % P;
	f[v] = (f[v * 2] + f[v * 2 + 1]) % P;
	return s;
}
int main() {
	int n, Q, rt, i, x, y, z, op;
	scanf("%d%d%d%d", &n, &Q, &rt, &P);
	for(i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(i = 1; i < n; i++) {
		scanf("%d%d", &x, &y);
		add(x, y), add(y, x);
	}
	dfs0(rt);
	dfs(rt, rt);
	for(i = 1; i <= n; i++) ins(1, 1, n, dfn[i], dfn[i], a[i]);
	while(Q--) {
		scanf("%d", &op);
		if(op == 1) {
			scanf("%d%d%d", &x, &y, &z);
			int f1 = tp[x], f2 = tp[y];
			while(f1 != f2) {
				if(dp[f1] < dp[f2]) swap(x, y), swap(f1, f2);
				ins(1, 1, n, dfn[f1], dfn[x], z);
				x = fa[f1], f1 = tp[x];
			}
			if(dp[x] < dp[y]) swap(x, y);
			ins(1, 1, n, dfn[y], dfn[x], z);
		}
		else if(op == 2) {
			scanf("%d%d%", &x, &y);
			ll ans = 0;
			int f1 = tp[x], f2 = tp[y];
			while(f1 != f2) {
				if(dp[f1] < dp[f2]) swap(x, y), swap(f1, f2);
				ans = (ans + find(1, 1, n, dfn[f1], dfn[x])) % P;
				x = fa[f1], f1 = tp[x];
			}
			if(dp[x] < dp[y]) swap(x, y);
			ans = (ans + find(1, 1, n, dfn[y], dfn[x])) % P;
			printf("%lld
", ans);
		}
		else if(op == 3) {
			scanf("%d%d", &x, &z);
			ins(1, 1, n, dfn[x], dfn[x] + si[x] - 1, z);
		}
		else {
			scanf("%d", &x);
			printf("%lld
", find(1, 1, n, dfn[x], dfn[x] + si[x] - 1));
		}
	}
	return 0;
}
哈哈哈哈哈哈哈哈哈哈
原文地址:https://www.cnblogs.com/LZA119/p/14623418.html