洛谷 P4426 - [HNOI/AHOI2018]毒瘤(虛樹+dp)
阿新 • • 發佈:2021-06-27
樹鏈剖分
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 3e5 + 9; template <typename T> inline void read(T &x) { register T f = 0, c = getchar(); for (; c < 48 || 57 < c; c = getchar()) if (c == '-') f = 1; for (x = 0; 48 <= c && c <= 57; c = getchar()) x = (x << 3) + (x << 1) + (c & 15); if (f) x = ~(--x); } template <typename T> inline void write(T x) { if (x < 0) putchar('-'), x = ~(--x); if (x > 9) write(x / 10); putchar(x % 10 | 48); } ll n, m, root, mod; struct segmentTree { struct node { int l, r, L, R; ll add, sum; }tr[N << 2]; inline void pushup(int p) {tr[p].sum = (tr[tr[p].l].sum*1ll + tr[tr[p].r].sum*1ll)%mod;} inline void pushdown(int p) { if (tr[p].add) { ll d = tr[p].add; tr[p].add = 0; (tr[tr[p].l].sum += d %mod * (tr[tr[p].l].R - tr[tr[p].l].L + 1)%mod)%=mod; (tr[tr[p].r].sum += d %mod * (tr[tr[p].r].R - tr[tr[p].r].L + 1)%mod)%=mod; (tr[tr[p].l].add += d)%=mod; (tr[tr[p].r].add += d)%=mod; } } inline void build(int l, int r, int p) { tr[p].l = p<<1; tr[p].r = p<<1|1; tr[p].L = l, tr[p].R = r; if (l == r) { tr[p].sum = 0, tr[p].add = 0; return; } ll mid = l + r >> 1; build(l, mid, tr[p].l),build(mid + 1, r, tr[p].r); pushup(p); } inline void add(ll l, ll r, ll p, ll k) { if (tr[p].L >= l && tr[p].R <= r) { tr[p].add += k; tr[p].add %= mod; tr[p].sum += (tr[p].R - tr[p].L + 1)%mod * k%mod; tr[p].sum %= mod; return; } pushdown(p); if (tr[tr[p].l].R >= l) add(l, r, tr[p].l, k); if (tr[tr[p].r].L <= r) add(l, r, tr[p].r,k); pushup(p); } inline int ask(int l, int r, int p) { int ret = 0; pushdown(p); if (tr[p].L >= l && tr[p].R <= r) return tr[p].sum%mod; if (tr[tr[p].l].R >= l) (ret += ask(l, r, tr[p].l))%=mod; if (tr[tr[p].r].L <= r) (ret += ask(l, r, tr[p].r))%=mod; return ret; } }T; vector<int>G[N]; int size[N], fa[N], dep[N], son[N]; int id[N], top[N], w[N]; int cnt; void dfs1(int u, int fat) { size[u] = 1; fa[u] = fat; if (fat != -1) dep[u] = dep[fat] + 1; int t = -1; for (auto v:G[u]) { if (v == fat)continue; dfs1(v, u); size[u] += size[v]; if (size[v] > t) { t = size[v]; son[u] = v; } } } void dfs2(int u, int fat) { top[u] = fat; id[u] = ++ cnt; if (w[u] != 0) { T.add(id[u], id[u], 1, w[u]); } if (son[u] == 0)return; dfs2(son[u], fat); for (auto v:G[u]) { if (v == fa[u] || v == son[u])continue; dfs2(v, v); } } void addPath(int u, int v, int k) { k %= mod; while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); T.add(id[top[u]], id[u],1, k); u = fa[top[u]]; } if (dep[u] > dep[v]) swap(u, v); T.add(id[u], id[v], 1,k); } int askPath(int u, int v) { ll ret = 0; while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); ret += T.ask(id[top[u]], id[u], 1); ret %= mod; u = fa[top[u]]; } if (dep[u] > dep[v]) swap(u, v); ret += T.ask(id[u], id[v], 1); ret %= mod;return ret; } void addSon(int u, int k) {k %= mod;T.add(id[u], id[u] + size[u] - 1,1, k);} int querySon(int u) { return T.ask(id[u], id[u] + size[u] - 1, 1); } void solve() { read(n), read(m), read(root), read(mod); T.build(1, n, 1); ll x; for (int i = 1; i <= n; i ++) { read(w[i]); w[i] %= mod; } for (int i = 1; i < n; i ++) { ll u, v; read(u), read(v); G[u].push_back(v); G[v].push_back(u); } dfs1(root, 0); dfs2(root, root); while (m--) { ll op; read(op); if (op == 1) { ll u, v, z; read(u), read(v), read(z); z %= mod; addPath(u, v, z); } if (op == 2) { ll u, v;read(u), read(v); write(askPath(u, v)%mod); puts(""); } if (op == 3) { int x, z;read(x), read(z); z %= mod; addSon(x, z); } if (op == 4) { int x; read(x); write(querySon(x) %mod); puts(""); } } } signed main() { ll t = 1;//cin >> t; while (t--) solve(); return 0; }