結果
問題 | No.900 aδδitivee |
ユーザー |
![]() |
提出日時 | 2019-10-04 22:45:44 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 360 ms / 2,000 ms |
コード長 | 6,124 bytes |
コンパイル時間 | 2,957 ms |
コンパイル使用メモリ | 219,068 KB |
最終ジャッジ日時 | 2025-01-07 20:42:49 |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 27 |
ソースコード
#include <bits/stdc++.h>#define int long longusing namespace std;struct HLD {int n;vector<vector<int>> adj;vector<int> sz, in, out, head, rev, par, depth;HLD(int n) : n(n), adj(n), sz(n), in(n), out(n), head(n), rev(n), par(n), depth(n) {}void add_edge(int a, int b) {assert(0 <= a && a < n && 0 <= b && b < n);adj[a].push_back(b);adj[b].push_back(a);}void dfs_sz(int v, int p, int d) {par[v] = p;sz[v] = 1;depth[v] = d;if (!adj[v].empty() && adj[v][0] == p) swap(adj[v][0], adj[v].back());for (int &s : adj[v]) {if (s == p) continue;dfs_sz(s, v, d + 1);sz[v] += sz[s];if (sz[adj[v][0]] < sz[s]) swap(adj[v][0], s);}}void dfs_hld(int v, int p, int ×) {in[v] = times++;rev[in[v]] = v;for (int &s : adj[v]) {if (s == p) continue;head[s] = adj[v][0] == s ? head[v] : s;dfs_hld(s, v, times);}out[v] = times;}void build() {dfs_sz(0, -1, 0);int t = 0;dfs_hld(0, -1, t);}int la(int v, int k) {while (1) {int u = head[v];if (in[v] - k >= in[u]) return rev[in[v] - k];k -= in[v] - in[u] + 1;v = par[u];}}int lca(int u, int v) {for (;; v = par[head[v]]) {if (in[u] > in[v]) swap(u, v);if (head[u] == head[v]) return u;}}template <typename Q, typename F, typename T>// qは閉区間に対応させること!!!!!!!!T query(int u, int v, const Q &q, const F &f, const T &e, bool edge = false) {T l = e, r = e;for (;; v = par[head[v]]) {if (in[u] > in[v]) swap(u, v), swap(l, r);if (head[u] == head[v]) break;l = f(q(in[head[v]], in[v]), l);}return f(f(q(in[u] + edge, in[v]), l), r);}template <typename Q>// qは閉区間に対応させること!!!!!!!!void update(int u, int v, const Q &q, bool edge = false) {for (;; v = par[head[v]]) {if (in[u] > in[v]) swap(u, v);if (head[u] == head[v]) break;q(in[head[v]], in[v]);}q(in[u] + edge, in[v]);}};// T0: 元の配列のモノイド// T1: T0に対する作用素モノイドtemplate <class T0, class T1>class SegmentTree {// k番目のノードにのlazyを伝搬void eval(int k, int len) {// 定数倍高速化if (lazy[k] == u1) return;// len個分のlazy[k]を評価node[k] = g(node[k], p(lazy[k], len));if (k < N - 1) {// 最下段でなければ下のlazyに伝搬lazy[2 * k + 1] = f1(lazy[2 * k + 1], lazy[k]);lazy[2 * k + 2] = f1(lazy[2 * k + 2], lazy[k]);}lazy[k] = u1;}// k番目のノード[l, r)について、[a, b)の範囲内にxを作用void update(int a, int b, T1 x, int k, int l, int r) {eval(k, r - l);if (b <= l || r <= a) return;if (a <= l && r <= b) {lazy[k] = f1(lazy[k], x);eval(k, r - l);} else {update(a, b, x, 2 * k + 1, l, (l + r) / 2);update(a, b, x, 2 * k + 2, (l + r) / 2, r);node[k] = f0(node[2 * k + 1], node[2 * k + 2]);}}// k番目のノード[l, r)について、[a, b)のクエリを求めるT0 query(int a, int b, int k, int l, int r) {if (r <= a || b <= l) return u0;eval(k, r - l);if (a <= l && r <= b) return node[k];T0 vl = query(a, b, 2 * k + 1, l, (l + r) / 2);T0 vr = query(a, b, 2 * k + 2, (l + r) / 2, r);return f0(vl, vr);}public:int sz; // 元の配列のサイズint N;vector<T0> node;vector<T1> lazy;// T0上の演算、単位元using F0 = function<T0(T0, T0)>;F0 f0;T0 u0;// T1上の演算、単位元using F1 = function<T1(T1, T1)>;F1 f1;T1 u1;// 作用using G = function<T0(T0, T1)>;G g;// 多数のt1(T1)に対するf1の合成using P = function<T1(T1, int)>;P p;SegmentTree(const vector<T0> &a, F0 f0, T0 u0, F1 f1, T1 u1, G g, P p): sz(a.size()), f0(f0), u0(u0), f1(f1), u1(u1), g(g), p(p) {for (N = 1; N < sz; N *= 2);node.resize(2 * N - 1);lazy.resize(2 * N - 1, u1);for (int i = 0; i < sz; i++) node[N - 1 + i] = a[i];for (int i = N - 2; i >= 0; i--) node[i] = f0(node[2 * i + 1], node[2 * i + 2]);}// [a, b)にxを作用void update(int a, int b, T1 x) { update(a, b, x, 0, 0, N); }void update(int a, T1 x) { update(a, a + 1, x); }// [a, b)T0 query(int a, int b) { return query(a, b, 0, 0, N); }T0 query(int a) { return query(a, a + 1); }};signed main() {ios::sync_with_stdio(false);cin.tie(0);int n;cin >> n;HLD hld(n);vector<tuple<int, int, int>> es;for (int i = 0; i < n - 1; i++) {int a, b, w;cin >> a >> b >> w;es.emplace_back(a, b, w);hld.add_edge(a, b);}hld.build();// Sum & AddSegmentTree<int, int> seg(vector<int>(n), plus<>(), 0, plus<>(), 0, plus<>(), multiplies<>());for (int i = 0; i < n - 1; i++) {int a = get<0>(es[i]);int b = get<1>(es[i]);int w = get<2>(es[i]);hld.update(a, b, [&](int u, int v) { return seg.update(u, v + 1, w); }, true);}int q;cin >> q;while (q--) {int t;cin >> t;if (t == 1) {int v, x;cin >> v >> x;seg.update(hld.in[v] + 1, hld.out[v], x);} else {int v;cin >> v;cout << hld.query(0, v, [&](int a, int b) { return seg.query(a, b + 1); },[](int a, int b) { return a + b; }, 0ll, true)<< '\n';}}}