From 719bb0ec83898db201c3a2632fcd63efe48259ac Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Sat, 29 Oct 2022 11:10:45 +0800 Subject: [PATCH] =?UTF-8?q?P3384=20=E3=80=90=E6=A8=A1=E6=9D=BF=E3=80=91?= =?UTF-8?q?=E8=BD=BB=E9=87=8D=E9=93=BE=E5=89=96=E5=88=86/=E6=A0=91?= =?UTF-8?q?=E9=93=BE=E5=89=96=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.luogu.com.cn/record/92005288 --- Luogu/P3384/P3384.cpp | 174 ++++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 76 deletions(-) diff --git a/Luogu/P3384/P3384.cpp b/Luogu/P3384/P3384.cpp index 6e4c819d..da436a83 100644 --- a/Luogu/P3384/P3384.cpp +++ b/Luogu/P3384/P3384.cpp @@ -1,79 +1,26 @@ #include +#include #include using std::cin; using std::cout; -using std::endl; +const char endl = '\n'; -const int N = 100005; +const int N = 1e5 + 5; -int p, a[N]; +int n, m, r, p, a[N]; std::vector g[N]; - -// Segment Tree -void build(int, int, int); - -// Heavy Path Decomposition int cnt, id[N], rid[N], fa[N], dep[N], siz[N], son[N], top[N]; -void dfs1(int, int); -void dfs2(int, int); -void modify_path(int, int, int); -void modify_tree(int, int); -long long query_path(int, int); -long long query_tree(int); - -int main() { - int n, m, r; - cin >> n >> m >> r >> p; - for (int i = 1; i <= n; i++) { - cin >> a[i]; - } - for (int i = 1; i < n; i++) { - int x, y; - cin >> x >> y; - g[x].push_back(y); - g[y].push_back(x); - } - dfs1(r, r); - dfs2(r, r); - build(1, 1, n); - while (m--) { - int op, x, y, z; - cin >> op; - if (op == 1) { - cin >> x >> y >> z; - modify_path(x, y, z); - } else if (op == 2) { - cin >> x >> y; - cout << query_path(x, y) << endl; - } else if (op == 3) { - cin >> x >> z; - modify_tree(x, z); - } else { - cin >> x; - cout << query_tree(x) << endl; - } - } - return 0; -} - -// === Segment Tree === struct node { int l, r; long long s, d; node() - : l(0), - r(0), - s(0), - d(0) {} + : l(0), r(0), s(0), d(0) {} node(int _l, int _r) - : l(_l), - r(_r), - s(0), - d(0) {} + : l(_l), r(_r), s(0), d(0) {} } tr[N << 2]; inline void pushup(int u) { @@ -82,22 +29,29 @@ inline void pushup(int u) { inline void pushdown(int u) { node &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1]; + left.s = (left.s + (left.r - left.l + 1) * root.d) % p; left.d = (left.d + root.d) % p; + right.s = (right.s + (right.r - right.l + 1) * root.d) % p; right.d = (right.d + root.d) % p; + root.d = 0; } void build(int u, int l, int r) { tr[u] = node(l, r); + if (l == r) { tr[u].s = a[rid[l]] % p; return; } + int mid = l + r >> 1; + build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); + pushup(u); } @@ -107,29 +61,35 @@ void modify(int u, int l, int r, int d) { tr[u].d = (tr[u].d + d) % p; return; } + pushdown(u); + int mid = tr[u].l + tr[u].r >> 1; + if (l <= mid) modify(u << 1, l, r, d); if (r > mid) modify(u << 1 | 1, l, r, d); + pushup(u); } long long query(int u, int l, int r) { if (l <= tr[u].l && tr[u].r <= r) return tr[u].s % p; pushdown(u); + int mid = tr[u].l + tr[u].r >> 1; long long res = 0; + if (l <= mid) res = (res + query(u << 1, l, r)) % p; if (r > mid) res = (res + query(u << 1 | 1, l, r)) % p; + return res; } -// == Heavy Path Decomposition === - void dfs1(int u, int f) { fa[u] = f; dep[u] = dep[f] + 1; siz[u] = 1; + for (int v : g[u]) { if (v == f) continue; dfs1(v, u); @@ -139,44 +99,106 @@ void dfs1(int u, int f) { } void dfs2(int u, int t) { - id[u] = ++cnt; - rid[id[u]] = u; + rid[id[u] = ++cnt] = u; top[u] = t; + if (!son[u]) return; + dfs2(son[u], t); + for (int v : g[u]) { - if (v == fa[u]) continue; - if (v == son[u]) continue; + if (v == fa[u] || v == son[u]) continue; + dfs2(v, v); } } -void modify_path(int u, int v, int d) { +void modify_path(int u, int v, int x) { while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) std::swap(u, v); - modify(1, id[top[u]], id[u], d); + modify(1, id[top[u]], id[u], x); u = fa[top[u]]; } + if (dep[u] < dep[v]) std::swap(u, v); - modify(1, id[v], id[u], d); + modify(1, id[v], id[u], x); } -long long query_path(int u, int v) { - long long sum = 0; +int query_path(int u, int v) { + int res = 0; + while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) std::swap(u, v); - sum = (sum + query(1, id[top[u]], id[u])) % p; + res = (res + query(1, id[top[u]], id[u])) % p; u = fa[top[u]]; } + if (dep[u] < dep[v]) std::swap(u, v); - sum = (sum + query(1, id[v], id[u])) % p; - return sum; + res = (res + query(1, id[v], id[u])) % p; + + return res; } -inline void modify_tree(int u, int d) { - modify(1, id[u], id[u] + siz[u] - 1, d); +void modify_tree(int u, int x) { + modify(1, id[u], id[u] + siz[u] - 1, x); } -inline long long query_tree(int u) { +int query_tree(int u) { return query(1, id[u], id[u] + siz[u] - 1); } + +int main() { + std::ios::sync_with_stdio(false); + cin.tie(nullptr); + + cin >> n >> m >> r >> p; + + for (int i = 1; i <= n; i++) { + cin >> a[i]; + } + + for (int i = 1, x, y; i < n; i++) { + cin >> x >> y; + + g[x].emplace_back(y); + g[y].emplace_back(x); + } + + dfs1(r, r); + dfs2(r, r); + build(1, 1, n); + + for (int i = 1; i <= m; i++) { + int op; + + cin >> op; + + if (op == 1) { + int x, y, z; + + cin >> x >> y >> z; + + modify_path(x, y, z); + } else if (op == 2) { + int x, y; + + cin >> x >> y; + + cout << query_path(x, y) << endl; + } else if (op == 3) { + int x, z; + + cin >> x >> z; + + modify_tree(x, z); + } else { // op == 4 + int x; + + cin >> x; + + cout << query_tree(x) << endl; + } + } + + return 0; +}