This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |