树剖18pts求调
查看原帖
树剖18pts求调
1119762
pray4u楼主2024/1/2 19:28
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#define rep(i, l, r) for(int i = (l); i <= (r); ++i)
#define endl '\n'
#define lson(x) x << 1
#define rson(x) x << 1 | 1
using namespace std;

typedef long long ll;
const int N = 1e5 + 7;

struct Edge {
	int v, nxt;
}e[N << 1];

struct Tree {
	int l, r;
	ll sum, laz;
}t[N << 2];

int n, m, rt, P;
int ec, head[N];
int siz[N], son[N], fst[N], depth[N], id[N], cnt, pre[N];
ll w1[N], w[N];

inline void add_e(int u, int v) {
	e[++ec].v = v;
	e[ec].nxt = head[u]; 
	head[u] = ec;
}

void init(int cur, int fath) {
	depth[cur] = depth[fath] + 1;
	siz[cur] = 1;
	for (int i = head[cur]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (v == fath) continue;
		init(v, cur);
		siz[cur] += siz[v];
		if (siz[v] > siz[son[cur]])
			son[cur] = v;
	}
}

void number(int cur, int fath, int f) {
	pre[cur] = fath;
	id[cur] = ++cnt;
	w[cnt] = w1[cur];
	fst[cur] = f;
	if (son[cur]) number(son[cur], cur, f);
	for (int i = head[cur]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (v == fath || v == son[cur]) continue;
		number(v, cur, v);
	}
}

inline void pushup(int x) { t[x].sum = (t[lson(x)].sum + t[rson(x)].sum) % P; }

inline void pushdown(int x) {
	ll tmp = t[x].laz; t[x].laz = 0;
	t[lson(x)].laz = (t[lson(x)].laz + tmp) % P;
	t[lson(x)].sum += tmp * (ll)(t[lson(x)].r - t[lson(x)].l + 1) % P;
	t[lson(x)].sum %= P;
	t[rson(x)].laz = (t[rson(x)].laz + tmp) % P;
	t[rson(x)].sum += tmp * (ll)(t[rson(x)].r - t[rson(x)].l + 1) % P;
	t[rson(x)].sum %= P;
}

void build(int cur, int l, int r) {
	t[cur].l = l; t[cur].r = r; t[cur].laz = 0;
	if (l == r) { t[cur].sum = w[l]; return; }
	t[cur].sum = 0;
	int mid = (l + r) >> 1;
	build(lson(cur), l, mid);
	build(rson(cur), mid + 1, r);
	pushup(cur);
}

inline bool is_intersect(int x, int L, int R) {
	return !(t[x].r < L || t[x].l > R);
}

void add(int cur, int L, int R, int val) {
	int l = t[cur].l, r = t[cur].r;
	if (L <= l && r <= R) {
		t[cur].sum = (t[cur].sum + val) % P;
		t[cur].laz = (t[cur].laz + val) % P;
		return;
	}
	pushdown(cur);
	if (is_intersect(lson(cur), L, R)) add(lson(cur), L, R, val);
	if (is_intersect(rson(cur), L, R)) add(rson(cur), L, R, val);
	pushup(cur);
}

ll query(int cur, int L, int R) {
	int l = t[cur].l, r = t[cur].r;
	if (L <= l && r <= R)
		return t[cur].sum;
	pushdown(cur);
	ll ans = 0;
	if (is_intersect(lson(cur), L, R)) {
		ans += query(lson(cur), L, R); ans %= P;
	}
	if (is_intersect(rson(cur), L, R)) {
		ans += query(rson(cur), L, R); ans %= P;
	}
	return ans;
}

void add_route(int a, int b, ll val) {
	while (fst[a] != fst[b]) {
		if (depth[fst[a]] < depth[fst[b]]) swap(a, b);
		add(1, id[fst[a]], id[a], val);
		a = pre[fst[a]];
	}
	if (id[a] > id[b]) swap(a, b);
	add(1, id[a], id[b], val);
}

ll query_route(int a, int b) {
	ll ans = 0;
	while (fst[a] != fst[b]) {
		if (depth[fst[a]] < depth[fst[b]]) swap(a, b);
		ans += query(1, id[fst[a]], id[a]);
		ans %= P;
		a = pre[fst[a]];
	}
	if (id[a] > id[b]) swap(a, b);
	ans += query(1, id[a], id[b]);
	ans %= P;
	return ans;
}

void add_t(int root, int val) {
	add(1, id[root], id[root] + siz[root] - 1, val);
}

ll query_t(int root) {
	return query(1, id[root], id[root] + siz[root] - 1);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> m >> rt >> P;
	rep(i, 1, n) cin >> w1[i];
	rep(i, 1, n - 1) {
		int x, y;
		cin >> x >> y;
		add_e(x, y); add_e(y, x);
	}
	init(rt, 0);
	number(rt, 0, rt);
	build(1, 1, cnt);
	rep(i, 1, m) {
		int opt; cin >> opt;
		switch (opt) {
			int x, y; ll val;
		case 1:
			cin >> x >> y >> val;
			add_route(x, y, val);
			break;
		case 2:
			cin >> x >> y;
			cout << query_route(x, y) << endl;
			break;
		case 3:
			cin >> x >> val;
			add_t(x, val);
			break;
		case 4:
			cin >> x;
			cout << query_t(x) << endl;
			break;
		}
	}
	return 0;
}
2024/1/2 19:28
加载中...