Submission #1323325

#TimeUsernameProblemLanguageResultExecution timeMemory
1323325TymondSumtree (INOI20_sumtree)C++20
100 / 100
566 ms47192 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; using ld = long double; #define fi first #define se second #define vi vector<int> #define vll vector<long long> #define pii pair<int, int> #define pll pair<long long, long long> #define pb push_back #define mp make_pair #define eb emplace_back #define all(x) (x).begin(), (x).end() #define sz(x) (int)(x).size() mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); mt19937_64 rng64(chrono::high_resolution_clock::now().time_since_epoch().count()); inline int rand(int l,int r){return uniform_int_distribution<int>(l, r)(rng);} inline ll rand(ll l,ll r){return uniform_int_distribution<ll>(l, r)(rng64);} #ifdef DEBUG auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";} auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";} #define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X) #else #define debug(...){} #endif struct custom_hash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; struct pair_hash{ size_t operator()(const pair<int,int>&x)const{ return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32)); } }; const int MOD = 1e9 + 7; const int MAXN = 3e5 + 7; const int BASE = (1 << 19); vi g[MAXN]; int parent[MAXN]; ll A[MAXN]; int tin[MAXN]; int tout[MAXN]; int id[MAXN]; int treeSpecial[2 * BASE + 7]; int treeSizes[2 * BASE + 7]; ll treeValues[2 * BASE + 7]; ll fact[2 * MAXN]; ll factInv[2 * MAXN]; int timer = 0; int siz[MAXN]; int n, q; void dfs(int v, int p){ parent[v] = p; id[timer] = v; tin[v] = timer++; siz[v] = 1; for(auto u : g[v]){ if(u == p){ continue; } dfs(u, v); siz[v] += siz[u]; } tout[v] = timer - 1; } void updSpecial(int v){ v = tin[v]; v += BASE; if(treeSpecial[v] == 0){ treeSpecial[v] = tout[id[v - BASE]]; }else{ treeSpecial[v] = 0; } v /= 2; while(v > 0){ treeSpecial[v] = max(treeSpecial[2 * v], treeSpecial[2 * v + 1]); v /= 2; } } int findAncestor(int v, int l, int p, int x){ if(treeSpecial[v] < tin[x] || l > tin[x]){ return -1; } if(l == p){ return id[v - BASE]; } int mid = (l + p) / 2; int r = findAncestor(2 * v + 1, mid + 1, p, x); if(r != -1){ return r; } return findAncestor(2 * v, l, mid, x); } int getAnc(int v){ return findAncestor(1, 0, BASE - 1, v); } ll inv(ll a){ if(a <= 1LL){ return a; } return (ll)MOD - (ll)(MOD / a) * inv(MOD % a) % MOD; } void preprocessing(){ dfs(1, 0); updSpecial(1); fact[0] = 1LL; for(int i = 1; i < 2 * MAXN; i++){ fact[i] = (ll)fact[i - 1] * i; fact[i] %= MOD; } factInv[2 * MAXN - 1] = inv(fact[2 * MAXN - 1]); for(int i = 2 * MAXN - 1; i >= 1; i--){ factInv[i - 1] = (ll)factInv[i] * i % MOD; } } ll calc(int N, int k){ if(N < k){ return 0LL; } return (ll)fact[N] * ((ll)factInv[N - k] * factInv[k] % MOD) % MOD; } void updSubtreeSize(int v, int val){ if(v == 0){ return; } v = tin[v]; v += BASE; while(v > 0){ treeSizes[v] += val; v /= 2; } } int querySubtreeSize(int v, int l, int p, int a, int b){ if(p < a || b < l){ return 0; } if(a <= l && p <= b){ return treeSizes[v]; } int mid = (l + p) / 2; return querySubtreeSize(2 * v, l, mid, a, b) + querySubtreeSize(2 * v + 1, mid + 1, p, a, b); } int getSubtreeSize(int v){ return siz[v] - querySubtreeSize(1, 0, BASE - 1, tin[v], tout[v]); } void updValue(int v, ll val){ if(v == 0){ return; } v = tin[v]; v += BASE; while(v > 0){ treeValues[v] += val; v /= 2; } } ll querySubtreeValues(int v, int l, int p, int a, int b){ if(p < a || b < l){ return 0LL; } if(a <= l && p <= b){ return treeValues[v]; } int mid = (l + p) / 2; return (ll)querySubtreeValues(2 * v, l, mid, a, b) + querySubtreeValues(2 * v + 1, mid + 1, p, a, b); } ll getSubtreeVal(int v){ return querySubtreeValues(1, 0, BASE - 1, tin[v], tout[v]); } ll ans; int cntZeros = 0; void deleteSubtree(int v){ // cerr << "DELETING: " << v << ' ' << ans << '\n'; ll s = getSubtreeVal(v); int sajz = getSubtreeSize(v); //cerr << "VAL: " << s << " SAJZ: " << sajz << '\n'; if(s > A[v]){ // cerr << "ZERO\n"; cntZeros--; }else{ // cerr << calc(A[v] - s + sajz - 1, sajz - 1) << '\n'; ans = (ll)ans * inv(calc(A[v] - s + sajz - 1, sajz - 1)) % MOD; } } void addSubtree(int v){ // cerr << "ADDING: " << v << ' ' << ans << '\n'; ll s = getSubtreeVal(v); int sajz = getSubtreeSize(v); // cerr << "VAL: " << s << " SAJZ: " << sajz << '\n'; if(s > A[v]){ // cerr << "ZERO\n"; cntZeros++; }else{ // cerr << calc(A[v] - s + sajz - 1, sajz - 1) << '\n'; ans = (ll)ans * calc(A[v] - s + sajz - 1, sajz - 1) % MOD; } } void addTag(int v, int r){ int x = getAnc(v); deleteSubtree(x); updSpecial(v); A[v] = r; int sajz = getSubtreeSize(v); // cerr << sajz << '\n'; updSubtreeSize(parent[v], sajz); updSubtreeSize(parent[x], -sajz); ll val = getSubtreeVal(v); updValue(parent[v], r - val); updValue(parent[x], val - r); addSubtree(v); addSubtree(x); } void deleteTag(int v){ updSpecial(v); int x = getAnc(v); deleteSubtree(x); deleteSubtree(v); int sajz = getSubtreeSize(v); updSubtreeSize(parent[v], -sajz); updSubtreeSize(parent[x], sajz); ll val = getSubtreeVal(v); updValue(parent[v], val - A[v]); updValue(parent[x], A[v] - val); A[v] = 0LL; addSubtree(x); } int main(){ ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL); cin >> n >> A[1]; for(int i = 2; i <= n; i++){ A[i] = 0LL; int a, b; cin >> a >> b; g[a].pb(b); g[b].pb(a); } preprocessing(); cin >> q; ans = calc(n + A[1] - 1, n - 1); cout << ans << '\n'; while(q--){ int type; cin >> type; if(type == 1){ int v, r; cin >> v >> r; addTag(v, r); }else{ int v; cin >> v; deleteTag(v); } if(cntZeros){ cout << "0\n"; }else{ cout << ans << '\n'; } // cerr << "========\n"; } return 0; }
#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...