萌新初学OI,求调树剖
查看原帖
萌新初学OI,求调树剖
448884
快乐的大童楼主2022/3/19 21:42

RTkkkk

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

inline int R() {
	int x = 0, f = 1;
	char ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch)) {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

inline void write(int x) {
	if (x < 0) {
		x = -x;
		putchar('-');
	}
	int y = 0;
	char z[40];
	while (x || !y) {
		z[y++] = x % 10 + 48;
		x /= 10;
	}
	while (y--)
		putchar(z[y]);
	putchar(10);
}
const int N = 1e5 + 5;

struct edge {
	int to, nxt;
} a[N << 1];
int head[N << 1], cnt;
int n, m, s, mod, w[N];

void add(int x, int y) {
	cnt++;
	a[cnt].to = y;
	a[cnt].nxt = head[x];
	head[x] = cnt;
}
int d[N << 2], b[N << 2];

int leftson(int x) {
	return x >> 1;
}

int rightson(int x) {
	return x >> 1 | 1;
}

void pushdown(int l, int r, int mid, int p) {
	d[leftson(p)] += (mid - l + 1) * b[p], d[rightson(p)] += (r - mid) * b[p];
	d[leftson(p)] %= mod, d[rightson(p)] %= mod;
	b[leftson(p)] += b[p], b[rightson(p)] += b[p];
	b[leftson(p)] %= mod, b[rightson(p)] %= mod;
	b[p] = 0;
}

void build(int l, int r, int p) {
	if (l == r) {
		d[p] = w[l] % mod;
		return;
	}
	int mid = (l + r) >> 1;
	build(l, mid, leftson(p));
	build(mid + 1, r, rightson(p));
	d[p] = (d[leftson(p)] + d[rightson(p)]) % mod;
}

void change(int L, int R, int l, int r, int p, int k) {
	if (L <= l && r <= R) {
		b[p] = (b[p] + k) % mod;
		d[p] = (d[p] + (r - l + 1) * k) % mod;
		return;
	}
	int mid = (l + r) >> 1;
	if (b[p])
		pushdown(l, r, mid, p);
	if (L <= mid)
		change(L, R, l, mid, leftson(p), k);
	if (R > mid)
		change(L, R, mid + 1, r, rightson(p), k);
	d[p] = (d[leftson(p)] + d[rightson(p)]) % mod;
}

int getsum(int L, int R, int l, int r, int p) {
	if (L <= l && r <= R)
		return d[p] % mod;
	int mid = (l + r) >> 1, res = 0;
	if (b[p])
		pushdown(l, r, mid, p);
	if (L <= mid)
		res = (res + getsum(L, R, l, mid, leftson(p))) % mod;
	if (R > mid)
		res = (res + getsum(L, R, mid + 1, r, rightson(p))) % mod;
	return res;
}
int dep[N], fa[N], son[N], siz[N];

void dfs1(int x, int y) {
	dep[x] = dep[y] + 1;
	fa[x] = y;
	siz[x] = 1;
	int tmp = 0;
	for (int i = head[x]; i; i = a[i].nxt) {
		int u = a[i].to;
		if (u == y)
			continue;
		dfs1(u, x);
		siz[x] += siz[u];
		if (siz[u] > tmp) {
			tmp = siz[u];
			son[x] = u;
		}
	}
}
int top[N], dfn[N], rk[N], val[N];

void dfs2(int x, int root) {
	dfn[x] = ++cnt;
	val[x] = w[x];
	top[x] = root;
	rk[dfn[x]] = x; //oi-wiki上有记载,但在luogu上就没了?
	if (!son[x])
		return;
	dfs2(son[x], root);
	for (int i = head[x]; i; i = a[i].nxt) {
		int u = a[i].to;
		if (u == fa[x] || u == son[x])
			continue;
		dfs2(u, u);
	}
}

void update(int l, int r, int k) {
	while (top[l] != top[r]) {
		if (dep[top[l]] < dep[top[r]])
			swap(l, r);
		change(dfn[top[l]], dfn[l], 1, n, 1, k);
		l = fa[top[l]];
	}
	if (dep[l] > dep[r])
		swap(l, r);
	change(dfn[l], dfn[r], 1, n, 1, k);
}

int query(int l, int r) {
	int res = 0;
	while (top[l] != top[r]) {
		if (dep[top[l]] < dep[top[r]])
			swap(l, r);
		res = (res + getsum(dfn[top[l]], dfn[l], 1, n, 1)) % mod;
		l = fa[top[l]];
	}
	if (dep[l] > dep[r])
		swap(l, r);
	res = (res + getsum(dfn[l], dfn[r], 1, n, 1)) % mod;
	return res;
}

int main() {
	n = R(), m = R(), s = R(), mod = R();
	for (int i = 1; i <= n; i++)
		w[i] = R();
	for (int i = 1, x, y; i < n; i++) {
		x = R(), y = R();
		add(x, y), add(y, x);
	}
	cnt = 0;
	dfs1(s, 0);
	dfs2(s, s);
	build(1, n, 1);
	for (int i = 1, op, l, r, v, k; i <= m; i++) {
		op = R();
		if (op == 1) {
			l = R(), r = R(), k = R();
			k %= mod;
			update(l, r, k);
		} else if (op == 2) {
			l = R(), r = R();
			write(query(l, r));
		} else if (op == 3) {
			v = R(), k = R();
			k %= mod;
			change(dfn[v], dfn[v] + siz[v] - 1, 1, n, 1, k);
		} else {
			v = R();
			write(getsum(dfn[v], dfn[v] + siz[v] - 1, 1, n, 1));
		}
	}
}
2022/3/19 21:42
加载中...