結果
問題 | No.900 aδδitivee |
ユーザー |
|
提出日時 | 2019-10-04 23:19:45 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 6,500 bytes |
コンパイル時間 | 2,383 ms |
コンパイル使用メモリ | 216,180 KB |
最終ジャッジ日時 | 2025-01-07 20:50:48 |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | WA * 2 |
other | WA * 27 |
ソースコード
#include <bits/stdc++.h>#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))#define ALL(x) std::begin(x), std::end(x)#define dump(x) cerr << #x " = " << x << endlusing namespace std;template <class T> using reversed_priority_queue = priority_queue<T, vector<T>, greater<T> >;template <class T, class U> inline void chmax(T & a, U const & b) { a = max<T>(a, b); }template <class T, class U> inline void chmin(T & a, U const & b) { a = min<T>(a, b); }template <typename X, typename T> auto make_table(X x, T a) { return vector<T>(x, a); }template <typename X, typename Y, typename Z, typename... Zs> auto make_table(X x, Y y, Z z, Zs... zs) { auto cont = make_table(y, z, zs...); returnvector<decltype(cont)>(x, cont); }template <typename T> ostream & operator << (ostream & out, vector<T> const & xs) { REP (i, (int)xs.size() - 1) out << xs[i] << ' '; if (not xs.empty()) out << xs.back(); return out; }/*** @arg g must be a tree* @note O(n) time* @note O(n) space on heap*/struct subtree_info_t {int parent; // in the entire treeint depth; // in the entire treeint size; // of the subtreeint height; // of the subtree};vector<subtree_info_t> prepare_subtree_info(vector<vector<int> > const & g, int root) {int n = g.size();vector<subtree_info_t> info(n, (subtree_info_t) { -1, -1, -1, -1 });vector<int> topological(n);topological[0] = root;info[root].parent = root;info[root].depth = 0;int r = 1;for (int l = 0; l < r; ++ l) {int i = topological[l];for (int j : g[i]) if (j != info[i].parent) {topological[r ++] = j;info[j].parent = i;info[j].depth = info[i].depth + 1;}}while ((-- r) >= 0) {int i = topological[r];info[i].size = 1;info[i].height = 0;for (int j : g[i]) if (j != info[i].parent) {info[i].size += info[j].size;info[i].height = max(info[i].height, info[j].height + 1);}}info[root].parent = -1;return info;}/*** @brief euler tour* @arg g must be a tree, directed or undirected* @note for constraints, see the unittest*/void do_euler_tour(vector<vector<int> > const & g, int root, vector<int> & tour, vector<int> & left, vector<int> & right) {int n = g.size();tour.clear();left.resize(n);right.resize(n);function<void (int, int)> go = [&](int x, int parent) {left[x] = tour.size();tour.push_back(x);for (int y : g[x]) if (y != parent) {go(y, x);}right[x] = tour.size();tour.push_back(x);};go(root, -1);}template <class OperatorMonoid>struct dual_segment_tree {typedef typename OperatorMonoid::value_type operator_type;typedef typename OperatorMonoid::target_type value_type;int n;std::vector<operator_type> f;std::vector<value_type> a;const OperatorMonoid op;dual_segment_tree() = default;dual_segment_tree(int a_n, value_type initial_value, OperatorMonoid const & a_op = OperatorMonoid()) : op(a_op) {n = 1; while (n < a_n) n *= 2;a.resize(n, initial_value);f.resize(n - 1, op.unit());}value_type point_get(int i) { // 0-basedvalue_type acc = a[i];for (i = (i + n) / 2; i > 0; i /= 2) { // 1-basedacc = op.apply(f[i - 1], acc);}return acc;}void range_apply(int l, int r, operator_type z) { // 0-based, [l, r)assert (0 <= l and l <= r and r <= n);range_apply(0, 0, n, l, r, z);}void range_apply(int i, int il, int ir, int l, int r, operator_type z) {if (l <= il and ir <= r) { // 0-basedif (i < f.size()) {f[i] = op.append(z, f[i]);} else {a[i - n + 1] = op.apply(z, a[i - n + 1]);}} else if (ir <= l or r <= il) {// nop} else {range_apply(2 * i + 1, il, (il + ir) / 2, 0, n, f[i]);range_apply(2 * i + 2, (il + ir) / 2, ir, 0, n, f[i]);f[i] = op.unit();range_apply(2 * i + 1, il, (il + ir) / 2, l, r, z);range_apply(2 * i + 2, (il + ir) / 2, ir, l, r, z);}}void point_set(int i, value_type z) {range_apply(i, i + 1, op.unit()); // to flush lazed opsa[i + n - 1] = z; // bug??}};struct add_linear_function_monoid {typedef std::pair<int64_t, int64_t> value_type;typedef std::pair<int64_t, int64_t> target_type;add_linear_function_monoid() = default;value_type unit() const {return std::make_pair(0, 0);}value_type append(value_type g, value_type f) const {int64_t fst = f.first + g.first;int64_t snd = f.second + g.second;return std::make_pair(fst, snd);}target_type apply(value_type f, target_type x) const {int64_t fst = f.first + x.first;int64_t snd = f.second + x.second;return std::make_pair(fst, snd);}};int main() {// inputint n; cin >> n;vector<vector<int> > g(n);vector<tuple<int, int, int64_t> > edges;REP (i, n - 1) {int x, y; int64_t c; cin >> x >> y >> c;g[x].push_back(y);g[y].push_back(x);edges.emplace_back(x, y, c);}// prepareconst int root = 0;auto info = prepare_subtree_info(g, root);vector<int> tour, left, right;do_euler_tour(g, root, tour, left, right);dual_segment_tree<add_linear_function_monoid> segtree(2 * n, make_pair(0, 0));for (auto edge : edges) {int x, y; int64_t c; tie(x, y, c) = edge;int z = (left[x] <= y and y < right[x] ? y : x);segtree.range_apply(left[z], right[z], make_pair(0, c));}// queryint q; cin >> q;while (q --) {int type; cin >> type;if (type == 1) {int x; int64_t c; cin >> x >> c;segtree.range_apply(left[x], right[x], make_pair(c, - c * info[x].depth));} else if (type == 2) {int y; cin >> y;int64_t a, b; tie(a, b) = segtree.point_get(left[y]);cout << a * info[y].depth + b << endl;}}return 0;}