結果
問題 | No.2439 Fragile Apple Tree |
ユーザー |
![]() |
提出日時 | 2023-08-19 00:14:47 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,820 ms / 10,000 ms |
コード長 | 13,821 bytes |
コンパイル時間 | 2,981 ms |
コンパイル使用メモリ | 219,024 KB |
最終ジャッジ日時 | 2025-02-16 11:09:45 |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 30 |
ソースコード
#include <bits/stdc++.h>#ifdef LOCAL#include <debug.hpp>#else#define debug(...) void(0)#endif#ifdef _MSC_VER#include <intrin.h>#endifnamespace atcoder {namespace internal {// @param n `0 <= n`// @return minimum non-negative `x` s.t. `n <= 2**x`int ceil_pow2(int n) {int x = 0;while ((1U << x) < (unsigned int)(n)) x++;return x;}// @param n `1 <= n`// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`constexpr int bsf_constexpr(unsigned int n) {int x = 0;while (!(n & (1 << x))) x++;return x;}// @param n `1 <= n`// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`int bsf(unsigned int n) {#ifdef _MSC_VERunsigned long index;_BitScanForward(&index, n);return index;#elsereturn __builtin_ctz(n);#endif}} // namespace internal} // namespace atcodernamespace atcoder {template <class S,S (*op)(S, S),S (*e)(),class F,S (*mapping)(F, S),F (*composition)(F, F),F (*id)()>struct lazy_segtree {public:lazy_segtree() : lazy_segtree(0) {}explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {log = internal::ceil_pow2(_n);size = 1 << log;d = std::vector<S>(2 * size, e());lz = std::vector<F>(size, id());for (int i = 0; i < _n; i++) d[size + i] = v[i];for (int i = size - 1; i >= 1; i--) {update(i);}}void set(int p, S x) {assert(0 <= p && p < _n);p += size;for (int i = log; i >= 1; i--) push(p >> i);d[p] = x;for (int i = 1; i <= log; i++) update(p >> i);}S get(int p) {assert(0 <= p && p < _n);p += size;for (int i = log; i >= 1; i--) push(p >> i);return d[p];}S prod(int l, int r) {assert(0 <= l && l <= r && r <= _n);if (l == r) return e();l += size;r += size;for (int i = log; i >= 1; i--) {if (((l >> i) << i) != l) push(l >> i);if (((r >> i) << i) != r) push((r - 1) >> i);}S sml = e(), smr = e();while (l < r) {if (l & 1) sml = op(sml, d[l++]);if (r & 1) smr = op(d[--r], smr);l >>= 1;r >>= 1;}return op(sml, smr);}S all_prod() { return d[1]; }void apply(int p, F f) {assert(0 <= p && p < _n);p += size;for (int i = log; i >= 1; i--) push(p >> i);d[p] = mapping(f, d[p]);for (int i = 1; i <= log; i++) update(p >> i);}void apply(int l, int r, F f) {assert(0 <= l && l <= r && r <= _n);if (l == r) return;l += size;r += size;for (int i = log; i >= 1; i--) {if (((l >> i) << i) != l) push(l >> i);if (((r >> i) << i) != r) push((r - 1) >> i);}{int l2 = l, r2 = r;while (l < r) {if (l & 1) all_apply(l++, f);if (r & 1) all_apply(--r, f);l >>= 1;r >>= 1;}l = l2;r = r2;}for (int i = 1; i <= log; i++) {if (((l >> i) << i) != l) update(l >> i);if (((r >> i) << i) != r) update((r - 1) >> i);}}template <bool (*g)(S)> int max_right(int l) {return max_right(l, [](S x) { return g(x); });}template <class G> int max_right(int l, G g) {assert(0 <= l && l <= _n);assert(g(e()));if (l == _n) return _n;l += size;for (int i = log; i >= 1; i--) push(l >> i);S sm = e();do {while (l % 2 == 0) l >>= 1;if (!g(op(sm, d[l]))) {while (l < size) {push(l);l = (2 * l);if (g(op(sm, d[l]))) {sm = op(sm, d[l]);l++;}}return l - size;}sm = op(sm, d[l]);l++;} while ((l & -l) != l);return _n;}template <bool (*g)(S)> int min_left(int r) {return min_left(r, [](S x) { return g(x); });}template <class G> int min_left(int r, G g) {assert(0 <= r && r <= _n);assert(g(e()));if (r == 0) return 0;r += size;for (int i = log; i >= 1; i--) push((r - 1) >> i);S sm = e();do {r--;while (r > 1 && (r % 2)) r >>= 1;if (!g(op(d[r], sm))) {while (r < size) {push(r);r = (2 * r + 1);if (g(op(d[r], sm))) {sm = op(d[r], sm);r--;}}return r + 1 - size;}sm = op(d[r], sm);} while ((r & -r) != r);return 0;}private:int _n, size, log;std::vector<S> d;std::vector<F> lz;void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }void all_apply(int k, F f) {d[k] = mapping(f, d[k]);if (k < size) lz[k] = composition(f, lz[k]);}void push(int k) {all_apply(2 * k, lz[k]);all_apply(2 * k + 1, lz[k]);lz[k] = id();}};} // namespace atcoderstruct HeavyLightDecomposition {std::vector<std::vector<int>> G; // child of vertex v on heavy edge is G[v].front() if it is not parent of vint n, time;std::vector<int> par, // parent of vertex vsub, // size of subtree whose root is vdep, // distance bitween root and vertex vhead, // vertex that is the nearest to root on heavy path of vertex vtree_id, // id of tree vertex v belongs tovertex_id, // id of vertex v (consecutive on heavy paths)vertex_id_inv; // vertex_id_inv[vertex_id[v]] = vHeavyLightDecomposition(int n): G(n),n(n),time(0),par(n, -1),sub(n),dep(n, 0),head(n),tree_id(n, -1),vertex_id(n, -1),vertex_id_inv(n) {}void add_edge(int u, int v) {assert(0 <= u and u < n);assert(0 <= v and v < n);G[u].emplace_back(v);G[v].emplace_back(u);}void build(std::vector<int> roots = {0}) {int tree_id_cur = 0;for (int& r : roots) {assert(0 <= r and r < n);dfs_sz(r);head[r] = r;dfs_hld(r, tree_id_cur++);}assert(time == n);for (int v = 0; v < n; v++) vertex_id_inv[vertex_id[v]] = v;}int idx(int v) const { return vertex_id[v]; }int la(int v, int k) const {assert(0 <= v and v < n);assert(0 <= k and k <= dep[v]);while (1) {int u = head[v];if (vertex_id[v] - k >= vertex_id[u]) return vertex_id_inv[vertex_id[v] - k];k -= vertex_id[v] - vertex_id[u] + 1;v = par[u];}}int lca(int u, int v) const {assert(0 <= u and u < n);assert(0 <= v and v < n);assert(tree_id[u] == tree_id[v]);for (;; v = par[head[v]]) {if (vertex_id[u] > vertex_id[v]) std::swap(u, v);if (head[u] == head[v]) return u;}}int jump(int s, int t, int i) const {assert(0 <= s and s < n);assert(0 <= t and t < n);assert(0 <= i);if (tree_id[s] != tree_id[t]) return -1;if (i == 0) return s;int p = lca(s, t), d = dep[s] + dep[t] - 2 * dep[p];if (d < i) return -1;if (dep[s] - dep[p] >= i) return la(s, i);return la(t, d - i);}int distance(int u, int v) const {assert(0 <= u and u < n);assert(0 <= v and v < n);assert(tree_id[u] == tree_id[v]);return dep[u] + dep[v] - 2 * dep[lca(u, v)];}template <typename F> void query_path(int u, int v, const F& f, bool vertex = false) const {assert(0 <= u and u < n);assert(0 <= v and v < n);assert(tree_id[u] == tree_id[v]);int p = lca(u, v);for (auto& e : ascend(u, p)) f(e.second, e.first + 1);if (vertex) f(vertex_id[p], vertex_id[p] + 1);for (auto& e : descend(p, v)) f(e.first, e.second + 1);}template <typename F> void query_path_noncommutative(int u, int v, const F& f, bool vertex = false) const {assert(0 <= u and u < n);assert(0 <= v and v < n);assert(tree_id[u] == tree_id[v]);int p = lca(u, v);for (auto& e : ascend(u, p)) f(e.first + 1, e.second);if (vertex) f(vertex_id[p], vertex_id[p] + 1);for (auto& e : descend(p, v)) f(e.first, e.second + 1);}template <typename F> void query_subtree(int u, const F& f, bool vertex = false) const {assert(0 <= u and u < n);f(vertex_id[u] + !vertex, vertex_id[u] + sub[u]);}private:void dfs_sz(int v) {sub[v] = 1;if (!G[v].empty() and G[v].front() == par[v]) std::swap(G[v].front(), G[v].back());for (int& u : G[v]) {if (u == par[v]) continue;par[u] = v;dep[u] = dep[v] + 1;dfs_sz(u);sub[v] += sub[u];if (sub[u] > sub[G[v].front()]) std::swap(u, G[v].front());}}void dfs_hld(int v, int tree_id_cur) {vertex_id[v] = time++;tree_id[v] = tree_id_cur;for (int& u : G[v]) {if (u == par[v]) continue;head[u] = (u == G[v][0] ? head[v] : u);dfs_hld(u, tree_id_cur);}}std::vector<std::pair<int, int>> ascend(int u, int v) const { // [u, v), v is ancestor of ustd::vector<std::pair<int, int>> res;while (head[u] != head[v]) {res.emplace_back(vertex_id[u], vertex_id[head[u]]);u = par[head[u]];}if (u != v) res.emplace_back(vertex_id[u], vertex_id[v] + 1);return res;}std::vector<std::pair<int, int>> descend(int u, int v) const { // (u, v], u is ancestor of vif (u == v) return {};if (head[u] == head[v]) return {{vertex_id[u] + 1, vertex_id[v]}};auto res = descend(u, par[head[v]]);res.emplace_back(vertex_id[head[v]], vertex_id[v]);return res;}};using namespace std;typedef long long ll;#define all(x) begin(x), end(x)constexpr int INF = (1 << 30) - 1;constexpr long long IINF = (1LL << 60) - 1;constexpr int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};template <class T> istream& operator>>(istream& is, vector<T>& v) {for (auto& x : v) is >> x;return is;}template <class T> ostream& operator<<(ostream& os, const vector<T>& v) {auto sep = "";for (const auto& x : v) os << exchange(sep, " ") << x;return os;}template <class T, class U = T> bool chmin(T& x, U&& y) { return y < x and (x = forward<U>(y), true); }template <class T, class U = T> bool chmax(T& x, U&& y) { return x < y and (x = forward<U>(y), true); }template <class T> void mkuni(vector<T>& v) {sort(begin(v), end(v));v.erase(unique(begin(v), end(v)), end(v));}template <class T> int lwb(const vector<T>& v, const T& x) { return lower_bound(begin(v), end(v), x) - begin(v); }ll op(ll l, ll r) { return min(l, r); }ll e() { return IINF; }ll mapping(ll l, ll r) { return l + r; }ll composition(ll l, ll r) { return l + r; }ll id() { return 0; }bool f(ll x) { return x > 0; }int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int N, Q;cin >> N >> Q;vector<int> a(N - 1), b(N - 1);vector<ll> c(N - 1);for (int i = 0; i < N - 1; i++) cin >> a[i] >> b[i] >> c[i], a[i]--, b[i]--;HeavyLightDecomposition HLD(N);for (int i = 0; i < N - 1; i++) HLD.add_edge(a[i], b[i]);HLD.build();vector<ll> init(N, e());vector<int> ch(N), par(N, -1);vector<vector<int>> G(N);for (int i = 0; i < N - 1; i++) {G[a[i]].emplace_back(i);G[b[i]].emplace_back(i);if (HLD.dep[a[i]] < HLD.dep[b[i]]) swap(a[i], b[i]);par[a[i]] = i;init[HLD.idx(a[i])] = c[i];ch[HLD.idx(a[i])] = a[i];}atcoder::lazy_segtree<ll, op, e, ll, mapping, composition, id> seg(init);int ans = N;vector<ll> sum(N, 0);vector<bool> alive(N - 1, true);auto kill = [&](int idx) {alive[idx] = false;seg.set(HLD.idx(a[idx]), IINF);ans--;auto q = [&](int l, int r) { seg.apply(l, r, sum[a[idx]]); };HLD.query_path(0, a[idx], q);};auto dfs = [&](auto self, int v) -> void {assert(v != 0);for (int& idx : G[v]) {int u = a[idx] ^ b[idx] ^ v;if (not alive[idx]) continue;kill(idx);self(self, u);}};auto query = [&](int v, int x) {sum[v] += x;auto q = [&](int l, int r) { seg.apply(l, r, -x); };HLD.query_path(0, v, q);int e = seg.min_left<f>(N) - 1;if (e == -1) return;int idx = par[ch[e]];kill(idx);dfs(dfs, a[idx]);};for (; Q--;) {int type;cin >> type;if (type == 1) {int v, x;cin >> v >> x;query(--v, x);} else {cout << ans << '\n';}}return 0;}