MnZn刚学OI1ms,树链剖分20pts求调
查看原帖
MnZn刚学OI1ms,树链剖分20pts求调
295509
你的洛楼主2022/12/9 16:21
// coding by cxz_0
#include <bits/stdc++.h>
#define awa cerr << "xlx is my superman!!!!!!!!!!!\n";
#define FOR(x,l,r) for(int (x) = (l); (x) <= (r); (x)++)
#define _FOR(x,l,r) for(int (x) = (r); (x) >= (l); (x)--)
#define gc getchar()
#define pb emplace_back
#define mp make_pair
#define pii pair<int, int >
#define PII pair<ll, ll >
#define fi first
#define se second
#define p_q priority_queue
// #define int ll
#define il inline
using namespace std;
typedef long long ll;

const int N = 1e5 + 5,MOD = 1e9 + 7;

namespace cxz_0
{
	il int read(int x=0,bool f=0,char c=gc){while(!isdigit(c))f=c=='-',c=gc;while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc;return f?-x:x;}
	il void write(int x){if(x<0)x=-x,putchar('-');if(x>9)write(x/10);putchar(x%10+'0');}
	il ll readl(ll x=0,bool f=0,char c=gc){while(!isdigit(c))f=c=='-',c=gc;while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc;return f?-x:x;}
	il void writel(ll x){if(x<0)x=-x,putchar('-');if(x>9)write(x/10);putchar(x%10+'0');}
	il int qpow(int a, int n, int p){int b=1;while(n){if(n&1)b=1ll*b*a%p;a=1ll*a*a%p;n>>=1;}return b;}
	il int max(int&a,int&b){return a>b?a:b;}
	il int min(int&a,int&b){return a<b?a:b;}
	il void swap(int&a,int&b){a^=b^=a^=b;}
	il int Mod(int x){return x>MOD?Mod(x-MOD):x;}
} using namespace cxz_0;

struct Node
{
	int nxt, to;
}e[N << 1];
struct Segtr
{
	int sum, add;
	#define lc (p << 1)
	#define rc (p << 1 | 1)
	#define MID int mid = (l + r) >> 1
}tr[N << 2];
int n, m, r, mod, a[N], cnt, tot, head[N], f[N], d[N], siz[N], son[N], rk[N], top[N], id[N];
//                                父亲节点  深度  子树个数  重儿子 dfs序对应节点 链顶 剖后编号
il void add_edge (int u, int v)
{
	e[++tot].to = v;
	e[tot].nxt = head[u];
	head[u] = tot;
}

il void pushup (int p)
{
	tr[p].sum = (tr[lc].sum + tr[rc].sum) % mod;
}

il void pushdown (int p, int l, int r)
{
	if (tr[p].add)
	{
		MID;
		(tr[lc].sum += tr[p].add * (mid - l + 1)) %= mod;
		(tr[rc].sum += tr[p].add * (r - mid)) %= mod;
		tr[lc].add += tr[p].add;
		tr[rc].add += tr[p].add;
		tr[p].add = 0;
	}
}

il void build (int p, int l, int r)
{
	if (l == r)
	{
		tr[p].sum = rk[l] % mod;
		return;
	}
	MID;
	build (lc, l, mid);
	build (rc, mid + 1, r);
	pushup (p);
}

il void modify (int p, int l, int r, int ql, int qr, int k)
{
	if (ql <= l && r <= qr)
	{
		(tr[p].add += k) %= mod;
		(tr[p].sum += k * (r - l + 1)) %= mod;
		return;
	}
	// pushdown (p, l, r);
	MID;
	if (mid >= ql) modify(lc, l, mid, ql, qr, k);
	if (mid < qr) modify(rc, mid + 1, r, ql, qr, k);
	pushup (p);
}

il int query (int p, int l, int r, int ql, int qr)
{
	if (ql <= l && r <= qr) return tr[p].sum;
	pushdown (p, l, r);
	MID;
	int ret = 0;
	if (mid >= ql) ret += query(lc, l, mid, ql, qr);
	if (mid < qr) ret += query(rc, mid + 1, r, ql, qr);
	return ret;
}

il void dfs1 (int u, int fa)
{
	f[u] = fa;
	d[u] = d[fa] + 1;
	siz[u] = 1;
	int maxson = 0;
	for (int i = head[u]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (v == fa) continue;
		dfs1 (v, u);
		siz[u] += siz[v];
		if (siz[v] > maxson) son[u] = v, maxson = siz[v];
	}
}

il void dfs2 (int u, int t)
{
	top[u] = t;
	id[u] = ++cnt;
	rk[cnt] = a[u];
	if (!son[u]) return;
	dfs2 (son[u], t);
	for (int i = head[u]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (v != son[u] && v != f[u]) dfs2 (v, v);
	}
}

il int sum (int x, int y)
{
	int ret = 0;
	while (top[x] != top[y])
	{
		if (d[top[x]] < d[top[y]]) swap(x, y);
		(ret += query(1, 1, n, id[top[x]], id[x])) %= mod;
		x = f[top[x]];
	}
	if (id[x] > id[y]) swap(x, y);
	return (ret + query (1, 1, n, id[x], id[y])) % mod;
}

il void update (int x, int y, int c)
{
	while (top[x] != top[y])
	{
		if (d[top[x]] < d[top[y]]) swap(x, y);
		modify (1, 1, n, id[top[x]], id[x], c);
		x = f[top[x]];
	}
	if (id[x] > id[y]) swap(x, y);
	modify (1, 1, n, id[x], id[y], c);
}

signed main()
{
#ifndef ONLINE_JUDGE
	double start = clock();
	freopen("P3384_2.in", "r", stdin);
	freopen("P3384.out", "w", stdout);
#endif
	n = read(), m = read(), r = read(), mod = read();
	FOR (i, 1, n) a[i] = read();
	FOR (i, 1, n - 1)
	{
		int u = read(), v = read();
		add_edge(u, v);
		add_edge(v, u);
	}
	dfs1 (r, 0);
	dfs2 (r, r);
	build (1, 1, n);
	// FOR (i, 1, n) cerr << id[i] << " ";
	cerr << endl;
	while (m--)
	{
		int op = read(), x = read(), y, z;
		if (op == 1)
		{
			y = read(), z = read();
			update (x, y, z);
		}
		else if (op == 2)
		{
			y = read();
			cout << sum (x, y) << "\n";
		}
		else if (op == 3)
		{
			y = read();
			modify (1, 1, n, id[x], id[x] + id[siz[x]] - 1, y);
		}
		else cout << query (1, 1, n, id[x], id[siz[x]] - 1) << "\n";
	}
#ifndef ONLINE_JUDGE
	cerr << "Time: " << 1e3 * (clock() - start) / CLOCKS_PER_SEC << " ms" << endl;
	awa
#endif
	return 0;
}

2022/12/9 16:21
加载中...