#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 ans, neg_vert;
ll Find(ll v)
{
// cout << "\nLooking at " << v << " and I see: ";
// for (auto [x, y] : tagged_on_path[id[v]])
// cout << x << ' ' << y << " | ";
// cout << '\n';
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, 0}))->second;
}
void print(ll n)
{
for (ll i = 1; i <= n; i++)
{
cout << i << ' ' << Find(i) << ' ' << val(i) << '\n';
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
ll n, q;
init(n, label[1], q);
prep(1, 0);
dfs(1, 0, 0);
ans = res(n, label[1]);
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 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... |