Submission #627297

#TimeUsernameProblemLanguageResultExecution timeMemory
627297AA_SurelySumtree (INOI20_sumtree)C++14
100 / 100
1006 ms71616 KiB
#include <bits/stdc++.h> #define FOR(i, x, n) for(int i = x; i < n; i++) #define F0R(i, n) FOR(i, 0, n) #define ROF(i, x, n) for(int i = n - 1; i >= x; i--) #define R0F(i, n) ROF(i, 0, n) #define WTF cout << "WTF" << endl #define IOS ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0) #define F first #define S second #define PB push_back #define ALL(x) x.begin(), x.end() #define RALL(x) x.rbegin(), x.rend() using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; typedef vector<int> VI; typedef vector<LL> VLL; typedef vector<PII> VPII; typedef vector<PLL> VPLL; const int N = 5e5 + 7; const int LOG = 22; const int INF = 1e9 + 7; const int MOD = 1e9 + 7; #define lc now << 1 #define rc now << 1 | 1 #define endl '\n' LL chs[N], vir[N], fact[N], ifact[N]; LL ans; VI adj[N], order; LL n, q, bad, cnt; LL head[N], par[N], s[N], height[N]; LL t[N][2]; struct SumTree { LL tree[N << 2]; void add(int lq, int rq, LL val, int now = 1, int ls = 0, int rs = n - 1) { if (rq < lq || rq < ls || rs < lq) return; if (lq <= ls && rs <= rq) { tree[now] += val; return; } int mid = (ls + rs) >> 1; add(lq, rq, val, lc, ls, mid); add(lq, rq, val, rc, mid + 1, rs); return; } LL get(int id, int now = 1, int ls = 0, int rs = n - 1) { if (ls == rs) return tree[now]; int mid = (ls + rs) >> 1; if (id <= mid) return get(id, lc, ls, mid) + tree[now]; return get(id, rc, mid + 1, rs) + tree[now]; } } val, sz; struct DescendTree { bool tree[N << 2]; bool arr[N]; void ch(int id, bool val, int now = 1, int ls = 0, int rs = n - 1) { if (ls == rs) { //cout << "tree[" << ls << ", " << rs << "] = " << tree[now] << endl; tree[now] = val; return; } int mid = (ls + rs) >> 1; if (id <= mid) ch(id, val, lc, ls, mid); else ch(id, val, rc, mid + 1, rs); tree[now] = tree[lc] | tree[rc]; //cout << "tree[" << ls << ", " << rs << "] = " << tree[now] << endl; return; } void change(int id, int val) { ch(id, val); arr[id] = val; } int g(int x) { return arr[x]; } int rightest(int q, int now = 1, int ls = 0, int rs = n - 1) { if (ls > q || !tree[now]) return n; if (ls == rs) return ls; int mid = (ls + rs) >> 1; int case1 = rightest(q, rc, mid + 1, rs); return (case1 == n ? rightest(q, lc, ls, mid) : case1); } } active; inline int pw(LL a, int b) { LL ret = 1; for(; b; b >>= 1, a = a * a % MOD) if (b & 1) ret = ret * a % MOD; return ret; } inline int nCr(int nn, int rr) { if (nn < rr || rr < 0) return 0; return (fact[nn] * ifact[rr] % MOD) * ifact[nn - rr] % MOD; } void init() { LL v0; cin >> n >> v0; val.add(0, 0, v0); F0R(i, n - 1) { int u, v; cin >> u >> v; adj[--u].PB(--v); adj[v].PB(u); } cin >> q; ans = 1; return; } void preD(int now, int p, int h = 0) { par[now] = p; s[now] = 1; height[now] = h; for(int on : adj[now]) if (on != p) { preD(on, now, h + 1); s[now] += s[on]; } return; } void precalc() { fact[0] = 1; FOR(i, 1, N) fact[i] = fact[i - 1] * i % MOD; ifact[N - 1] = pw(fact[N - 1], MOD - 2); R0F(i, N - 1) ifact[i] = ifact[i + 1] * (i + 1) % MOD; iota(head, head + n, 0); F0R(i, n) { sort(ALL(adj[i]), [](const int &a, const int &b) {return s[a] < s[b];}); if (i) adj[i].pop_back(); reverse(ALL(adj[i])); } return; } void dfs(int now) { order.PB(now); t[now][0] = cnt++; if (!adj[now].empty()) head[ adj[now][0] ] = head[now]; for(int on : adj[now]) dfs(on); t[now][1] = cnt; return; } void updChoose(int now) { if (!chs[now]) bad--; else ans = (ans * pw(chs[now], MOD - 2)) % MOD; LL val_now = val.get(t[now][0]); LL sz_now = sz.get(t[now][0]); chs[now] = nCr(val_now + sz_now - 1, sz_now - 1); if (!chs[now]) bad++; else ans = (ans * chs[now]) % MOD; return; } void remChoose(int now) { if (!chs[now]) bad--; else ans = (ans * pw(chs[now], MOD - 2)) % MOD; chs[now] = 1; return; } int getUpperActive(int v) { while(!active.g(t[v][0])) { int pl = order[ active.rightest(t[v][0]) ]; if (t[pl][0] >= t[ head[v] ][0]) v = pl; else v = par[ head[v] ]; } return v; } void addUpTo(int v, int z, LL x1, LL x2) { while(height[v] >= height[z]) { int w = (height[ head[v] ] >= height[z] ? head[v] : z); sz.add(t[w][0], t[v][0], x1); val.add(t[w][0], t[v][0], x2); v = par[w]; } return; } void addTag() { int v, x; cin >> v >> x; v--; val.add(t[v][0], t[v][0], x); LL sz_v = sz.get(t[v][0]); LL val_v = val.get(t[v][0]); int up = getUpperActive(v); //cout << "up is " << up << endl; addUpTo(par[v], up, -sz_v, -val_v); vir[v] = x; updChoose(up); updChoose(v); //cout << "t[" << v << "][0] = " << t[v][0] << endl; active.change(t[v][0], 1); return; } void remTag() { int v; cin >> v; v--; LL sz_v = sz.get(t[v][0]); LL val_v = val.get(t[v][0]); int up = getUpperActive(par[v]); addUpTo(par[v], up, sz_v, val_v); val.add(t[v][0], t[v][0], -vir[v]); updChoose(up); remChoose(v); active.change(t[v][0], 0); return; } int main() { IOS; init(); height[n] = -1; par[0] = n; preD(0, n); precalc(); dfs(0); F0R(i, n) sz.add(t[i][0], t[i][0], s[i]); active.change(0, 1); fill(chs, chs + n, 1); updChoose(0); cout << ans << endl; while(q--) { int tp; cin >> tp; if (tp == 1) addTag(); else remTag(); cout << (bad ? 0 : ans) << endl; } }
#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...