結果
問題 | No.1038 TreeAddQuery |
ユーザー |
|
提出日時 | 2024-01-05 00:20:08 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,468 ms / 4,000 ms |
コード長 | 20,611 bytes |
コンパイル時間 | 2,883 ms |
コンパイル使用メモリ | 213,112 KB |
実行使用メモリ | 151,632 KB |
最終ジャッジ日時 | 2024-09-27 18:54:56 |
合計ジャッジ時間 | 24,894 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 24 |
ソースコード
#line 1 "template/template.hpp"#include <algorithm>#include <bit>#include <bitset>#include <cassert>#include <chrono>#include <climits>#include <cmath>#include <complex>#include <cstddef>#include <cstdint>#include <cstdlib>#include <cstring>#include <functional>#include <iomanip>#include <iostream>#include <limits>#include <map>#include <memory>#include <numbers>#include <numeric>#include <optional>#include <queue>#include <random>#include <ranges>#include <set>#include <stack>#include <string>#include <tuple>#include <type_traits>#include <unordered_map>#include <unordered_set>#include <utility>#include <vector>#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)#define rrep(i, a, n) for (int i = ((int)(n)-1); i >= (int)(a); i--)#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)#define RRep(i, a, n) for (i64 i = ((i64)(n)-i64(1)); i >= (i64)(a); i--)#define all(v) (v).begin(), (v).end()#define rall(v) (v).rbegin(), (v).rend()#line 2 "template/debug_template.hpp"#line 4 "template/debug_template.hpp"namespace ebi {#ifdef LOCAL#define debug(...) \std::cerr << "LINE: " << __LINE__ << " [" << #__VA_ARGS__ << "]:", \debug_out(__VA_ARGS__)#else#define debug(...)#endifvoid debug_out() {std::cerr << std::endl;}template <typename Head, typename... Tail> void debug_out(Head h, Tail... t) {std::cerr << " " << h;if (sizeof...(t) > 0) std::cerr << " :";debug_out(t...);}} // namespace ebi#line 2 "template/int_alias.hpp"#line 4 "template/int_alias.hpp"namespace ebi {using ld = long double;using std::size_t;using i8 = std::int8_t;using u8 = std::uint8_t;using i16 = std::int16_t;using u16 = std::uint16_t;using i32 = std::int32_t;using u32 = std::uint32_t;using i64 = std::int64_t;using u64 = std::uint64_t;using i128 = __int128_t;using u128 = __uint128_t;} // namespace ebi#line 2 "template/io.hpp"#line 7 "template/io.hpp"namespace ebi {template <typename T1, typename T2>std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {return os << pa.first << " " << pa.second;}template <typename T1, typename T2>std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {return os >> pa.first >> pa.second;}template <typename T>std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {for (std::size_t i = 0; i < vec.size(); i++)os << vec[i] << (i + 1 == vec.size() ? "" : " ");return os;}template <typename T>std::istream &operator>>(std::istream &os, std::vector<T> &vec) {for (T &e : vec) std::cin >> e;return os;}template <typename T>std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {if (opt) {os << opt.value();} else {os << "invalid value";}return os;}void fast_io() {std::cout << std::fixed << std::setprecision(15);std::cin.tie(nullptr);std::ios::sync_with_stdio(false);}} // namespace ebi#line 2 "template/utility.hpp"#line 5 "template/utility.hpp"#line 7 "template/utility.hpp"namespace ebi {template <class T> inline bool chmin(T &a, T b) {if (a > b) {a = b;return true;}return false;}template <class T> inline bool chmax(T &a, T b) {if (a < b) {a = b;return true;}return false;}template <class T> T safe_ceil(T a, T b) {if (a % b == 0)return a / b;else if (a >= 0)return (a / b) + 1;elsereturn -((-a) / b);}template <class T> T safe_floor(T a, T b) {if (a % b == 0)return a / b;else if (a >= 0)return a / b;elsereturn -((-a) / b) - 1;}constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;constexpr int INF = std::numeric_limits<int>::max() / 2;const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};} // namespace ebi#line 2 "tree/contour_query_on_tree.hpp"#line 6 "tree/contour_query_on_tree.hpp"#line 2 "tree/centroid_decomposition.hpp"#line 7 "tree/centroid_decomposition.hpp"namespace ebi {namespace internal {template <class F>void centroid_decomposition_dfs_naive(const std::vector<int> &par,const std::vector<int> &original_vs,F f) {const int n = (int)par.size();assert(par.size() == original_vs.size());int center = -1;std::vector<int> sz(n, 1);for (const int v : std::views::iota(0, n) | std::views::reverse) {if (sz[v] >= (n + 1) / 2) {center = v;break;}sz[par[v]] += sz[v];}std::vector<int> color(n, -1);std::vector<int> vs = {center};color[center] = 0;int c = 1;for (const int v : std::views::iota(1, n)) {if (par[v] == center) {vs.emplace_back(v);color[v] = c++;}}if (center > 0) {for (int v = par[center]; v != -1; v = par[v]) {vs.emplace_back(v);color[v] = c;}c++;}for (const int v : std::views::iota(0, n)) {if (color[v] == -1) {vs.emplace_back(v);color[v] = color[par[v]];}}std::vector<int> index_ptr(c + 1, 0);for (const int v : std::views::iota(0, n)) {index_ptr[color[v] + 1]++;}for (const int i : std::views::iota(0, c)) {index_ptr[i + 1] += index_ptr[i];}auto counter = index_ptr;std::vector<int> ord(n);for (auto v : vs) {ord[counter[color[v]]++] = v;}std::vector<int> relabel(n);for (const int v : std::views::iota(0, n)) {relabel[ord[v]] = v;}std::vector<int> original_vs2(n);for (const int v : std::views::iota(0, n)) {original_vs2[relabel[v]] = original_vs[v];}std::vector<int> relabel_par(n, -1);for (int v : std::views::iota(1, n)) {int a = relabel[v];int b = relabel[par[v]];if (a > b) std::swap(a, b);relabel_par[b] = a;}f(relabel_par, original_vs2, index_ptr);for (const int i : std::views::iota(1, c)) {int l = index_ptr[i], r = index_ptr[i + 1];std::vector<int> par1(r - l, -1);std::vector<int> original_vs1(r - l, -1);for (int v : std::views::iota(l, r)) {par1[v - l] = (relabel_par[v] == 0 ? -1 : relabel_par[v] - l);original_vs1[v - l] = original_vs2[v];}centroid_decomposition_dfs_naive(par1, original_vs1, f);}return;}template <class F>void one_third_centroid_decomposition(const std::vector<int> &par,const std::vector<int> &original_vs,F f) {const int n = (int)par.size();assert(n > 1);if (n == 2) return;int center = -1;std::vector<int> sz(n, 1);for (const int v : std::views::iota(0, n) | std::views::reverse) {if (sz[v] >= (n + 1) / 2) {center = v;break;}sz[par[v]] += sz[v];}std::vector<int> color(n, -1);std::vector<int> ord(n, -1);ord[center] = 0;int t = 1;int red = n - sz[center];for (int v = par[center]; v != -1; v = par[v]) {ord[v] = t++;color[v] = 0;}for (const int v : std::views::iota(1, n)) {if (par[v] == center && 3 * (red + sz[v]) <= 2 * (n - 1)) {red += sz[v];ord[v] = t++;color[v] = 0;}}for (const int v : std::views::iota(1, n)) {if (v != center && color[v] == -1 && color[par[v]] == 0) {ord[v] = t++;color[v] = 0;}}const int n0 = t - 1;for (const int v : std::views::iota(1, n)) {if (v != center && color[v] == -1) {ord[v] = t++;color[v] = 1;}}assert(t == n);const int n1 = n - 1 - n0;std::vector<int> par0(n0 + 1, -1), par1(n1 + 1, -1), par2(n, -1);std::vector<int> original_vs0(n0 + 1), original_vs1(n1 + 1),original_vs2(n);for (const int i : std::views::iota(0, n)) {int v = ord[i];original_vs2[v] = original_vs[i];if (color[i] != 1) {original_vs0[v] = original_vs[i];}if (color[i] != 0) {int idx = std::max(v - n0, 0);original_vs1[idx] = original_vs[i];}}for (const int v : std::views::iota(1, n)) {int a = ord[v], b = ord[par[v]];if (a > b) std::swap(a, b);par2[b] = a;if (color[v] != 1 && color[par[v]] != 1) {par0[b] = a;}if (color[v] != 0 && color[par[v]] != 0) {par1[b - n0] = std::max(a - n0, 0);}}f(par2, original_vs2, n0, n1);one_third_centroid_decomposition(par0, original_vs0, f);one_third_centroid_decomposition(par1, original_vs1, f);return;}template <class F>void one_third_centroid_decomposition_virtual_real(const std::vector<int> &par, const std::vector<int> &original_vs,const std::vector<int> &is_real, F f) {const int n = (int)par.size();assert(n > 1);if (n == 2) {if (is_real[0] && is_real[1]) {f(par, original_vs, {0, 1});}return;}int center = -1;std::vector<int> sz(n, 1);for (const int v : std::views::iota(0, n) | std::views::reverse) {if (sz[v] >= (n + 1) / 2) {center = v;break;}sz[par[v]] += sz[v];}std::vector<int> color(n, -1);std::vector<int> ord(n, -1);ord[center] = 0;int t = 1;int red = n - sz[center];for (int v = par[center]; v != -1; v = par[v]) {ord[v] = t++;color[v] = 0;}for (const int v : std::views::iota(1, n)) {if (par[v] == center && 3 * (red + sz[v]) <= 2 * (n - 1)) {red += sz[v];ord[v] = t++;color[v] = 0;}}for (const int v : std::views::iota(1, n)) {if (v != center && color[v] == -1 && color[par[v]] == 0) {ord[v] = t++;color[v] = 0;}}const int n0 = t - 1;for (const int v : std::views::iota(1, n)) {if (v != center && color[v] == -1) {ord[v] = t++;color[v] = 1;}}assert(t == n);const int n1 = n - 1 - n0;std::vector<int> par0(n0 + 1, -1), par1(n1 + 1, -1), par2(n, -1);std::vector<int> original_vs0(n0 + 1), original_vs1(n1 + 1),original_vs2(n);std::vector<int> is_real0(n0 + 1), is_real1(n1 + 1), is_real2(n);for (const int i : std::views::iota(0, n)) {int v = ord[i];original_vs2[v] = original_vs[i];is_real2[v] = is_real[i];if (color[i] != 1) {original_vs0[v] = original_vs[i];is_real0[v] = is_real[i];}if (color[i] != 0) {int idx = std::max(v - n0, 0);original_vs1[idx] = original_vs[i];is_real1[idx] = is_real[i];}}for (const int v : std::views::iota(1, n)) {int a = ord[v], b = ord[par[v]];if (a > b) std::swap(a, b);par2[b] = a;if (color[v] != 1 && color[par[v]] != 1) {par0[b] = a;}if (color[v] != 0 && color[par[v]] != 0) {par1[b - n0] = std::max(a - n0, 0);}}if (is_real[center]) {color.assign(n, -1);color[0] = 0;for (const int v : std::views::iota(1, n)) {if (is_real2[v]) color[v] = 1;}f(par2, original_vs2, color);is_real0[0] = is_real1[0] = is_real2[0] = 0;}color.assign(n, -1);for (const int v : std::views::iota(1, n)) {if (is_real2[v]) {color[v] = int(v > n0);}}f(par2, original_vs2, color);one_third_centroid_decomposition_virtual_real(par0, original_vs0, is_real0,f);one_third_centroid_decomposition_virtual_real(par1, original_vs1, is_real1,f);return;}} // namespace internaltemplate <int MODE, class F>void centroid_decomposition(const std::vector<std::vector<int>> &tree, F f) {int n = (int)tree.size();if (n == 1) return;std::vector<int> bfs_order(n), par(n, -1);bfs_order[0] = 0;int l = 0, r = 1;while (l < r) {int v = bfs_order[l++];for (auto nv : tree[v]) {if (nv == par[v]) continue;bfs_order[r++] = nv;par[nv] = v;}}assert(l == n && r == n);{std::vector<int> relabel(n);for (int i : std::views::iota(0, n)) {relabel[bfs_order[i]] = i;}std::vector<int> relabel_par(n, -1);for (int i : std::views::iota(1, n)) {relabel_par[relabel[i]] = relabel[par[i]];}std::swap(par, relabel_par);}static_assert(MODE == 0 || MODE == 1 || MODE == 2);if constexpr (MODE == 0) {internal::centroid_decomposition_dfs_naive(par, bfs_order, f);} else if constexpr (MODE == 1) {internal::one_third_centroid_decomposition(par, bfs_order, f);} else {internal::one_third_centroid_decomposition_virtual_real(par, bfs_order, std::vector<int>(n, 1), f);}}} // namespace ebi#line 8 "tree/contour_query_on_tree.hpp"namespace ebi {struct contour_query_on_tree {contour_query_on_tree(const std::vector<std::vector<int>> &tree): n(int(tree.size())) {int t = 0;range = {0};auto f = [&](const std::vector<int> &par, const std::vector<int> &vs,const std::vector<int> &color) -> void {int sz = (int)par.size();std::vector<int> depth(sz, 0);for (const int v : std::views::iota(1, sz)) {depth[v] += depth[par[v]] + 1;}std::vector<int> red, blue;for (const int v : std::views::iota(0, sz)) {if (color[v] == 0) {red.emplace_back(v);} else if (color[v] == 1) {blue.emplace_back(v);} elseassert(color[v] == -1);}if (red.empty() || blue.empty()) return;int max_red = -1;for (const int v : red) {vertexs.emplace_back(vs[v]);number.emplace_back(t);dep.emplace_back(depth[v]);max_red = max_red < depth[v] ? depth[v] : max_red;}range.emplace_back(range.back() + max_red + 1);t++;int max_blue = -1;for (const int v : blue) {vertexs.emplace_back(vs[v]);number.emplace_back(t);dep.emplace_back(depth[v]);max_blue = max_blue < depth[v] ? depth[v] : max_blue;}range.emplace_back(range.back() + max_blue + 1);t++;};centroid_decomposition<2>(tree, f);index_ptr.assign(n + 1, 0);for (const int v : vertexs) {index_ptr[v + 1]++;}for (const int v : std::views::iota(0, n)) {index_ptr[v + 1] += index_ptr[v];}index.resize(index_ptr.back());auto counter = index_ptr;for (int i = 0; const int v : vertexs) {index[counter[v]++] = i;i++;}}std::vector<std::pair<int, int>> get_contour_from_vertex(int v, int l,int r) const {assert(0 <= v && v < n);std::vector<std::pair<int, int>> res;for (const int idx :std::ranges::subrange(index.begin() + index_ptr[v],index.begin() + index_ptr[v + 1])) {int label = number[idx] ^ 1;int left = l - dep[idx], right = r - dep[idx];int max = range[label + 1] - range[label];if (left < 0) left = 0;if (right > max) right = max;if (left < right) {res.emplace_back(range[label] + left, range[label] + right);}}return res;}std::vector<int> get_vertex(int v) const {assert(0 <= v && v < n);std::vector<int> res;for (const int idx :std::ranges::subrange(index.begin() + index_ptr[v],index.begin() + index_ptr[v + 1])) {int label = number[idx];assert(range[label] + dep[idx] < range[label + 1]);res.emplace_back(range[label] + dep[idx]);}return res;}int size() const {return range.back();}private:int n;std::vector<int> vertexs, number, dep;std::vector<int> index, index_ptr;std::vector<int> range;};} // namespace ebi#line 2 "graph/template.hpp"#line 4 "graph/template.hpp"namespace ebi {template <class T> struct Edge {int to;T cost;Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}};template <class T> struct Graph : std::vector<std::vector<Edge<T>>> {using std::vector<std::vector<Edge<T>>>::vector;void add_edge(int u, int v, T w, bool directed = false) {(*this)[u].emplace_back(v, w);if (directed) return;(*this)[v].emplace_back(u, w);}};struct graph : std::vector<std::vector<int>> {using std::vector<std::vector<int>>::vector;void add_edge(int u, int v, bool directed = false) {(*this)[u].emplace_back(v);if (directed) return;(*this)[v].emplace_back(u);}};} // namespace ebi#line 2 "data_structure/dual_segtree.hpp"#line 7 "data_structure/dual_segtree.hpp"namespace ebi {template <class F, F (*merge)(F, F), F (*id)()> struct dual_segtree {private:void all_apply(int i, F f) {d[i] = merge(f, d[i]);}void push(int i) {assert(i < sz);all_apply(2 * i, d[i]);all_apply(2 * i + 1, d[i]);d[i] = id();}public:dual_segtree(int n) : dual_segtree(std::vector<F>(n, id())) {}dual_segtree(const std::vector<F> &a): n(a.size()),sz(std::bit_ceil(a.size())),lg2(std::countr_zero((unsigned int)(sz))) {d = std::vector<F>(2 * sz, id());for (int i : std::views::iota(sz, sz + n)) {d[i] = a[i - sz];}}void apply(int l, int r, F f) {assert(0 <= l && l <= r && r <= n);if (l == r) return;l += sz;r += sz;for (int i : std::views::iota(1, lg2 + 1) | std::views::reverse) {if (((l >> i) << i) != l) push(l >> i);if (((r >> i) << i) != r) push((r - 1) >> i);}while (l < r) {if (l & 1) all_apply(l++, f);if (r & 1) all_apply(--r, f);l >>= 1;r >>= 1;}}F get(int p) {assert(0 <= p && p < n);p += sz;for (int i : std::views::iota(1, lg2 + 1) | std::views::reverse) {push(p >> i);}return d[p];}private:int n, sz, lg2;std::vector<F> d;};} // namespace ebi#line 5 "a.cpp"namespace ebi {i64 op(i64 a, i64 b) {return a + b;}i64 e() {return 0;}void main_() {int n,q;std::cin >> n >> q;graph g(n);rep(i,0,n-1) {int a,b;std::cin >> a >> b;a--; b--;g.add_edge(a, b);}std::vector<i64> res(n, 0);contour_query_on_tree cq(g);dual_segtree<i64, op, e> seg(cq.size());while(q--) {int x,y;i64 z;std::cin >> x >> y >> z;x--;i64 ans = res[x];for(auto i: cq.get_vertex(x)) {ans += seg.get(i);}std::cout << ans << '\n';y++;res[x] += z;for(auto [l, r]: cq.get_contour_from_vertex(x, 0, y)) {seg.apply(l, r, z);}}}} // namespace ebiint main() {ebi::fast_io();int t = 1;// std::cin >> t;while (t--) {ebi::main_();}return 0;}