This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
//In His Name
#include <bits/stdc++.h>
//#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("avx2")
using namespace std;
#define ll long long
#define int ll
typedef pair<int, int> pii;
#define F first
#define S second
#define pb push_back
#define bug(x) cout << "Ah shit , here we go again : " << x <<endl
#define all(x) x.begin() , x.end()
const int maxn = 3e5 + 10, MOD = 1e9 + 7;
const ll INF = 1e18 + 100;
int n , q , root , h[maxn] , st[maxn] , fn[maxn] , ti , val[maxn] , fact[maxn] , sub[maxn] , ans;
vector<int> adj[maxn];
void Dfs(int v , int p){
st[v] = ++ti , h[v] = h[p]+1;
for(int u : adj[v]) if(u != p) Dfs(u , v) , sub[v] += sub[u];
sub[v] += adj[v].size();
if(v != 1) sub[v]--;
fn[v] = ti;
}
int Power(int x , int y){
if(y == 0) return 1;
int tmp = Power(x , y/2);
tmp = tmp * tmp % MOD;
if(y & 1) tmp = tmp * x % MOD;
return tmp;
}
int Sayale(int x , int y){ // paeen bala
return fact[x+y] * Power(fact[x] * fact[y] % MOD , MOD-2) % MOD;
}
struct FindPar{
set<pii , greater<pii>> hoom[4*maxn];
void Update(int id , int L , int R , int l , int r , int w , int ty){
if(L == l and R == r) {
if(ty == 0) hoom[id].erase({h[w] , w});
else hoom[id].insert({h[w] , w});
return;
}
int mid = (L+R) >> 1 , lc = id << 1 , rc = lc | 1;
if(l < mid) Update(lc , L , mid , l , min(r, mid) , w , ty);
if(r > mid) Update(rc , mid , R , max(l , mid) , r , w , ty);
}
int Get(int id , int L , int R , int idx , int v){
int res = 0;
if(hoom[id].size()) res = hoom[id].begin()->S;
if(L + 1 == R) return res;
int mid = (L+R) >> 1 , lc = id << 1 , rc = lc | 1 , res2;
if(idx < mid) res2 = Get(lc , L , mid , idx , v);
else res2 = Get(rc , mid , R , idx , v);
return h[res] > h[res2] ? res : res2;
}
}Find;
struct Segment{
int toop[4*maxn] , sabad[4*maxn]; // barchasb - raas
void Update(int id , int L , int R , int idx , int w , int ty){ // ty = 0 -> toop , ty = 1 -> sabad
if(L+1 == R){
ty == 0 ? toop[id] += w : sabad[id] += w;
return;
}
int mid = (L+R) >> 1 , lc = id << 1 , rc = lc | 1;
if(idx < mid) Update(lc , L , mid , idx , w , ty);
else Update(rc , mid , R , idx , w , ty);
toop[id] = toop[lc] + toop[rc];
sabad[id] = sabad[lc] + sabad[rc];
}
pii Get(int id , int L , int R , int l , int r){
if(L == l and R == r) return{toop[id] , sabad[id]};
int mid = (L+R) >> 1 , lc = id << 1 , rc = lc | 1;
pii res1 = {0,0} , res2 = {0 , 0};
if(l < mid) res1 = Get(lc , L , mid , l , min(r , mid));
if(r > mid) res2 = Get(rc , mid , R , max(l , mid) , r);
return {res1.F + res2.F , res1.S + res2.S};
}
}Seg;
int32_t main(){
ios_base::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
fact[0] = 1;
for(int i = 1 ; i < maxn ; i++) fact[i] = fact[i-1] * i % MOD;
cin >> n >> root;
for(int i = 1 ; i < n ; i++){
int u , v;
cin >> u >> v;
adj[u].pb(v);
adj[v].pb(u);
}
Dfs(1 , 0);
cin >> q;
ans = Sayale(sub[1] , root);
val[1] = root;
cout << ans << '\n';
Find.Update(1 , 1 , n+1 , st[1] , fn[1]+1 , 1 , 1);
Seg.Update(1 , 1 , n+1 , st[1] , root , 0);
Seg.Update(1 , 1 , n+1 , st[1] , sub[1] , 1);
while(q--){
int ty , v , w;
cin >> ty;
if(ans <= 0) ans = 1;
if(ty == 1){
cin >> v >> w;
val[v] = w;
if(val[v] < 0){
ans = 0;
continue;
}
int par = Find.Get(1 , 1 , n+1 , st[v] , v);
pii x = Seg.Get(1 , 1 , n+1 , st[v] , fn[v]+1);
pii y = Seg.Get(1 , 1 , n+1 , st[par]+1 , fn[par]+1);
ans = ans * Power(Sayale(sub[par]-y.S , val[par]-y.F) , MOD-2) % MOD;
ans = ans * Sayale(sub[v] - x.S , val[v]-x.F) % MOD;
Seg.Update(1 , 1 , n+1 , st[v] , val[v] - x.F , 0);
Seg.Update(1 , 1 , n+1 , st[v] , sub[v] - x.S + 1 , 1);
y = Seg.Get(1 , 1 , n+1 , st[par]+1 , fn[par]+1);
ans = ans * Sayale(sub[par]-y.S , val[par]-y.F) % MOD;
Find.Update(1 , 1 , n+1 , st[v] , fn[v]+1 , v , 1);
}
else{
cin >> v;
int par = Find.Get(1 , 1 , n+1 , st[v]-1 , v);
pii x = Seg.Get(1 , 1 , n+1 , st[v]+1 , fn[v]+1);
pii y = Seg.Get(1 , 1 , n+1 , st[par]+1 , fn[par]+1);
ans = ans * Power(Sayale(sub[v]-x.S, val[v]-x.F) , MOD-2) % MOD;
ans = ans * Power(Sayale(sub[par]-y.S , val[par]-y.F) , MOD-2) % MOD;
Seg.Update(1 , 1 , n+1 , st[v] , -(sub[v] - x.F + 1) , 1);
Seg.Update(1 , 1 , n+1 , st[v] , -(val[v] - x.S) , 0);
val[v] = 0;
y = Seg.Get(1 , 1 , n+1 , st[par]+1 , fn[par]+1);
ans = ans * Sayale(sub[par]-y.S , val[par]-y.F) % MOD;
Find.Update(1 , 1 , n+1 , st[v] , fn[v]+1 , v , 0);
}
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... |