제출 #1312662

#제출 시각아이디문제언어결과실행 시간메모리
13126624QT0RSumtree (INOI20_sumtree)C++20
10 / 100
293 ms60860 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long const ll mod = 1e9 + 7; vector<ll> graph[200003]; ll fat[200003]; ll label[200003]; ll dep[200003]; ll id[200003]; ll seg_id[200003]; ll prep_siz[200003]; vector<ll> whole_path[200003]; vector<set<pair<ll, ll>>> tagged_on_path(1); ll iter, seg_iter; const ll base = 1 << 18; ll tree[2 * base]; void add(ll a, ll b, ll x) { a += base - 1; b += base + 1; while (a / 2 != b / 2) { if (!(a & 1)) tree[a + 1] += x; if (b & 1) tree[b - 1] += x; a >>= 1; b >>= 1; } } ll query(ll v) { v += base; ll ans = 0; while (v) { ans += tree[v]; v >>= 1; } return ans; } void path_add(ll v, ll x) { if (v == 0) return; add(seg_id[whole_path[id[v]][0]], seg_id[v], x); path_add(fat[whole_path[id[v]][0]], x); } void path_add(ll v, ll p, ll x) { path_add(v, x); path_add(fat[p], -x); } ll val(ll v) { return query(seg_id[v]); } void prep(ll v, ll p) { fat[v] = p; prep_siz[v] = 1; for (auto u : graph[v]) { if (u == p) continue; dep[u] = dep[v] + 1; prep(u, v); prep_siz[v] += prep_siz[u]; } sort(graph[v].begin(), graph[v].end(), [&](ll v, ll u) { return prep_siz[v] > prep_siz[u]; }); } void dfs(ll v, ll p, ll ind) { id[v] = ind; seg_id[v] = ++seg_iter; tree[seg_iter + base] = prep_siz[v]; whole_path[ind].push_back(v); for (auto u : graph[v]) { if (u == p) continue; if (2 * prep_siz[u] > prep_siz[v]) dfs(u, v, ind); else { tagged_on_path.push_back({}); dfs(u, v, ++iter); } } } ll fact[500003]; ll fact_inv[500003]; ll fast_pow(ll a, ll b) { if (b == 1) return a; ll cur = fast_pow(a, b / 2); cur = (cur * cur) % mod; if (b & 1) cur = (cur * a) % mod; return cur; } void init(ll &n, ll &r, ll &q) { cin >> n >> r; for (ll i = 1, a, b; i < n; i++) { cin >> a >> b; graph[a].push_back(b); graph[b].push_back(a); } cin >> q; fact[0] = 1; for (ll i = 1; i <= 500002; i++) fact[i] = (i * fact[i - 1]) % mod; fact_inv[500002] = fast_pow(fact[500002], mod - 2); for (ll i = 500001; i >= 0; i--) fact_inv[i] = ((i + 1) * fact_inv[i + 1]) % mod; } ll res(ll siz, ll tag) { ll wyn = fact[siz + tag - 1]; wyn = (wyn * fact_inv[tag]) % mod; wyn = (wyn * fact_inv[siz - 1]) % mod; return wyn; } ll Find(ll v) { if (tagged_on_path[id[v]].empty() || ((*tagged_on_path[id[v]].begin()).first > dep[v])) return Find(fat[whole_path[id[v]][0]]); return prev(tagged_on_path[id[v]].lower_bound({dep[v] + 1, -1}))->second; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); ll n, q; init(n, label[1], q); if (n == 1) { for (ll i = 0; i < q+1; i++) { cout << "1\n"; } return 0; } prep(1, 0); dfs(1, 0, 0); ll ans = res(n, label[1]), neg_vert = 0; cout << ans << '\n'; tagged_on_path[id[1]].insert({dep[1], 1}); for (ll i = 1, t, v, tag; i <= q; i++) { cin >> t >> v; if (t == 1) cin >> tag; ll up = Find(fat[v]), val_of_v = val(v), val_of_up = val(up); if (val_of_up < 0) neg_vert--; else ans = (ans * fast_pow(res(val_of_up, label[up]), mod - 2)) % mod; if (t == 1) { label[v] = tag; ans = (ans * res(val_of_v, label[v])) % mod; tagged_on_path[id[v]].insert({dep[v], v}); path_add(fat[v], up, -val_of_v); val_of_up -= val_of_v; } else { val_of_up += val_of_v; path_add(fat[v], up, val_of_v); tagged_on_path[id[v]].erase({dep[v], v}); ans = (ans * fast_pow(res(val_of_v, label[v]), mod - 2)) % mod; label[v] = 0; } if (val_of_up < 0) neg_vert++; else ans = (ans * res(val_of_up, label[up])) % mod; if (neg_vert) cout << "0\n"; else cout << ans << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...