/*
stuff i need to do:
- might need to make a permutation inverter
- compute preorder, make a translation table from tree index to preorder index
- compute subtree sizes; make sure to index by preorder
- compute BFS order, make a translation table from tree index to BFS index (and vice versa)
- segtree over BFS order
subroutine: binary search for the first node that's a subtree of some other node and is at some given depth
observation: dfs index is monotonic over a single level of a tree
first node invariant: l = set of all nodes such that dep[i] < dep_targ or dep[i] == dep_targ and dfs_order[i] < dfs_order[targ]
r is the first node
last node invariant: r = set of all nodes such that dep[i] > dep_targ or dep[i] == dep_targ and not within tree and sz[dfs_order[targ]] < dfs_order[i] - dfs_order[targ] + 1ll
*/
#pragma GCC optimize("O3", "unroll-loops")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> v3i;
typedef vector<v3i> v4i;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef pair<int, int> pi;
typedef pair<ll, ll> pll;
typedef vector<pi> vpi;
typedef vector<pll> vpll;
#define INF(dt) numeric_limits<dt>::max()
#define NINF(dt) numeric_limits<dt>::min()
#define pb push_back
ll MOD = 1ll; // TODO set this to the correct value later on!
void printv(const vll& a) {
for(ll v : a) cerr << v << " ";
cerr << endl;
}
/*
input: a target node (in original indexing) and a target depth
output: two node indices (in BFS order)
first node invariant: l = set of all nodes such that dep[i] < dep_targ or dep[i] == dep_targ and dfs_order[i] < dfs_order[targ]
r is the first node
last node invariant: r = set of all nodes such that dep[i] > dep_targ or dep[i] == dep_targ and not within tree and sz[dfs_order[targ]] < dfs_order[i] - dfs_order[targ] + 1ll
l is the last node
*/
void find_par(ll i, ll pr, vll& par, const vvll& adj) {
par[i] = pr;
for(ll j : adj[i]) {
if(j == pr) continue;
find_par(j, i, par, adj);
}
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
// inputting graph information
ll n;
cin >> n >> MOD;
vvll adj(n, vll());
for(ll i = 0ll; i < n - 1ll; i++) {
ll a, b;
cin >> a >> b;
a--; b--;
adj[a].pb(b);
adj[b].pb(a);
}
// find parents
vll par(n, -1ll);
find_par(0ll, 0ll, par, adj);
// store updates
const ll MAXD = 40ll;
vvll upds(n, vll(MAXD + 1ll, 1ll));
vll init(n, 0ll);
for(ll i = 0ll; i < n; i++) cin >> init[i];
// perform the updates
ll q;
cin >> q;
while(q--) {
int qt;
cin >> qt;
if(qt == 1) {
// upd
ll x, d, w;
cin >> x >> d >> w;
x--;
ll cur_d = d;
ll cur_n = x;
while(cur_d >= 0ll) {
if(par[cur_n] != cur_n) {
// "normal" update
upds[cur_n][cur_d] *= w;
upds[cur_n][cur_d] %= MOD;
if(cur_d > 0ll) {
upds[cur_n][cur_d - 1ll] *= w;
upds[cur_n][cur_d - 1ll] %= MOD;
}
cur_d--;
} else {
// update to completion
for(ll i = 0ll; i <= cur_d; i++) {
upds[cur_n][i] *= w;
upds[cur_n][i] %= MOD;
}
break;
}
cur_n = par[cur_n];
}
} else {
// qry
ll x;
cin >> x;
x--;
ll res = init[x];
ll cur_n = x;
ll cur_d = 0ll;
while(cur_d <= MAXD) {
res = (res * upds[cur_n][cur_d]) % MOD;
cur_d++;
if(par[cur_n] == cur_n) break;
cur_n = par[cur_n];
}
cout << res << "\n";
}
}
cout << flush;
return 0;
}
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |