Submission #646491

#TimeUsernameProblemLanguageResultExecution timeMemory
646491danikoynovArboras (RMI20_arboras)C++14
24 / 100
5072 ms26308 KiB
/** ____ ____ ____ ____ ____ ____ ||l |||e |||i |||n |||a |||d || ||__|||__|||__|||__|||__|||__|| |/__\|/__\|/__\|/__\|/__\|/__\| **/ #include<bits/stdc++.h> #define endl '\n' using namespace std; typedef long long ll; void speed() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } const int maxn = 1e5 + 10; const ll mod = 1e9 + 7; int n, q; int heavy[maxn], ch_idx[maxn], ch_pos[maxn], ch_head[maxn]; int par[maxn], depth[maxn], sub[maxn], strong[maxn]; ll dp[maxn][2], dis[maxn]; vector < pair < int, ll > > g[maxn]; void dfs(int v) { heavy[v] = -1; strong[v] = -1; for (pair < int, ll > nb : g[v]) { if (nb.first == par[v]) continue; depth[nb.first] = depth[v] + 1; dfs(nb.first); if (heavy[v] == -1 || sub[nb.first] > sub[heavy[v]]) heavy[v] = nb.first; if (dp[nb.first][0] + nb.second >= dp[v][0]) { dp[v][1] = dp[v][0]; dp[v][0] = dp[nb.first][0] + nb.second; strong[v] = nb.first; } else if (dp[nb.first][0] + nb.second > dp[v][1]) { dp[v][1] = dp[nb.first][0] + nb.second; } } } ll ans = 0; vector < int > ver; vector < pair < ll, ll > > st; set < int > weak; vector < pair < ll, ll > > tree; vector < ll > lazy; void build_tree(int root, int left, int right) { if (left == right) { tree[root] = st[left]; return; } int mid = (left + right) / 2; build_tree(root * 2, left, mid); build_tree(root * 2 + 1, mid + 1, right); } void build_chain() { for (int i = 0; i < ver.size(); i ++) { st.push_back({dp[ver[i]][0], dp[ver[i]][1]}); if (i != (int)(ver.size()) - 1) { if (strong[ver[i]] != ver[i + 1]) weak.insert(i); } } tree.resize(ver.size() * 4); lazy.resize(ver.size() * 4); build_tree(1, 0, (int)st.size() - 1); } void push_lazy(int root, int left, int right) { ///if (lazy[root].first == lazy[root].second && lazy[root].first == 0) if (left == right) { tree[root].first += lazy[root]; } else { lazy[root * 2] += lazy[root]; lazy[root * 2 + 1] += lazy[root]; } lazy[root] = 0; } pair < ll, ll > get_node(int root, int left, int right, int idx) { ///cout << left << " " << right << " " << root << " " << idx << " " << endl; if (lazy[root] != 0) push_lazy(root, left, right); if (left == right) return tree[root]; int mid = (left + right) / 2; if (idx <= mid) return get_node(root * 2, left, mid, idx); return get_node(root * 2 + 1, mid + 1, right, idx); } void set_node(int root, int left, int right, int idx, pair < ll,ll > val) { ///cout << root << " " << left << " " << right << endl; if (lazy[root] != 0) push_lazy(root, left, right); if (left == right) { tree[root] = val; return; } int mid = (left + right) / 2; if (idx <= mid) set_node(root * 2, left, mid, idx, val); else set_node(root * 2 + 1, mid + 1, right, idx, val); } void update_range(int root, int left, int right, int qleft, int qright, ll val) { if (lazy[root] != 0) push_lazy(root, left, right); if (left == qleft && right == qright) { lazy[root] = val; push_lazy(root, left, right); return; } int mid = (left + right) / 2; if (qright <= mid) update_range(root * 2, left, mid, qleft, qright, val); else if (qleft > mid) update_range(root * 2 + 1, mid + 1, right, qleft, qright, val); else { update_range(root * 2, left, mid, qleft, mid, val); update_range(root * 2 + 1, mid + 1, right, mid + 1, qright, val); } /**if (left > qright || right < qleft) return; if (left >= qleft && right <= qright) { lazy[root] = val; push_lazy(root, left, right); return; } int mid = (left + right) / 2; update_range(root * 2, left, mid, qleft, qright, val); update_range(root * 2 + 1, mid + 1, right, qleft, qright, val);*/ } pair < ll, ll > get_element(int v) { ///cout << "get_element query" << v << endl; return get_node(1, 0, (int)(ver.size()) - 1, ch_pos[v]); } void set_element(int v, pair < ll, ll > val) { //cout << "set_element query" << v << endl; set_node(1, 0, (int)(ver.size()) - 1, ch_pos[v], val); } void update_path(int lf, int rf, ll val) { update_range(1, 0, (int)(ver.size()) - 1, lf, rf, val); } int ch_st[maxn], ch_en[maxn]; int nxt; void hld(int v, int head) { ch_pos[v] = ver.size(); ver.push_back(v); ch_head[v] = head; ch_idx[v] = nxt; if (v == head) ch_st[nxt] = ch_pos[v]; ch_en[nxt] = ch_pos[v]; if (heavy[v] != -1) { hld(heavy[v], head); } for (pair < int, ll > nb : g[v]) { if (nb.first == par[v] || nb.first == heavy[v]) continue; nxt ++; hld(nb.first, nb.first); } } void update(int v, ll d) { ll cur = dp[v][0]; dis[v] += d; while(true) { if (v == 0) break; cur = cur + dis[v]; ///cout << v << " :: " << cur << endl; if (strong[par[v]] == v) { ans = ans + cur - dp[par[v]][0]; ans = (ans + mod) % mod; dp[par[v]][0] = cur; v = par[v]; continue; } if (cur <= dp[par[v]][1]) break; if (cur <= dp[par[v]][0]) { ans = ans + cur - dp[par[v]][1]; ans = (ans + mod) % mod; dp[par[v]][1] = cur; break; } ans = ans + cur - dp[par[v]][1]; ans = (ans + mod) % mod; dp[par[v]][1] = dp[par[v]][0]; dp[par[v]][0] = cur; strong[par[v]] = v; v = par[v]; } /**cout << "------------" << endl; for (int i = 0; i < n; i ++) cout << dp[i][0] << " " << dp[i][1] << endl; cout << "------------" << endl;*/ } void update_edge(int v, ll d) { dis[v] += d; pair < ll, ll > cur, aft; while(true) { ///cout << "here " << v << endl; if (v == 0) break; if (ch_head[v] == v) { cur = get_element(v); aft = get_element(par[v]); if (strong[par[v]] == v) { ans = (ans + cur.first + dis[v] - aft.first) % mod; aft.first = cur.first + dis[v]; set_element(par[v], aft); v = par[v]; } else { if (cur.first + dis[v] <= aft.second) break; if (cur.first + dis[v] <= aft.first) { ans = (ans + cur.first + dis[v] - aft.second) % mod; aft.second = cur.first + dis[v]; ///cout << v << " " << par[v] << " " << aft.first << " " << aft.second << endl; set_element(par[v], aft); break; } ans = (ans + cur.first + dis[v] - aft.second) % mod; if (strong[par[v]] == ver[ch_pos[par[v]] + 1]) weak.insert(ch_pos[par[v]]); strong[par[v]] = v; aft.second = aft.first; aft.first = cur.first + dis[v]; set_element(par[v], aft); v = par[v]; continue; } } else { int pos = ch_pos[ch_head[v]]; if (!weak.empty()) { set < int > :: iterator it = weak.lower_bound(ch_pos[v]); if (it != weak.begin()) { it = prev(it); pos = max(*it + 1, pos); } } /**for (int x : ch[ch_idx[v]].weak) cout << x << " "; cout << endl;*/ ///cout << pos << " " << ch_pos[v] << endl; if (pos == ch_pos[v]) { cur = get_element(v); aft = get_element(par[v]); if (cur.first + dis[v] <= aft.second) break; if (cur.first + dis[v] <= aft.first) { ans = (ans + cur.first + dis[v] - aft.second) % mod; aft.second = cur.first + dis[v]; set_element(par[v], aft); continue; } strong[par[v]] = v; weak.erase(pos - 1); ans = (ans + cur.first + dis[v] - aft.second) % mod; aft.second = aft.first; aft.first = cur.first + dis[v]; set_element(par[v], aft); pair < ll, ll > sad = get_element(par[v]); ///cout << sad.first << " " << sad.second << endl; v = par[v]; continue; } else { cur = get_element(v); aft = get_element(par[v]); ll diff = cur.first + dis[v] - aft.first; ans = (ans + diff * (ch_pos[v] - pos)) % mod; update_path(pos, ch_pos[v] - 1, diff); v = ver[pos]; continue; } } } } void solve() { cin >> n; for (int i = 1; i < n; i ++) cin >> par[i]; for (int i = 1; i < n; i ++) { cin >> dis[i]; g[par[i]].push_back({i, dis[i]}); } par[0] = -1; dfs(0); hld(0, 0); /**for (int i = 0; i < size(); i ++) { cout << i << " : "; for (int v : ch[i].ver) cout << v << " "; cout << endl; }*/ build_chain(); for (int j = 0; j < (int)ver.size() - 1; j ++) { if (strong[ver[j]] != ver[j + 1] && ch_idx[ver[j]] == ch_idx[ver[j + 1]]) weak.insert(j); } cin >> q; for (int i = 0; i < n; i ++) ans = (ans + dp[i][0] + dp[i][1]) % mod; cout << ans << endl; ///get_element(1); ///get_element(0); ///set_element(par[1], {1, 0}); ///get_element(par[1]); ///exit(0); for (int i = 0; i < q; i ++) { ///if (i % 10000 == 0) ///cout << "YEP" << endl; int v; ll d; cin >> v >> d; ///update(v, d); update_edge(v, d); cout << ans << endl; } } int main() { ///freopen("input.txt", "r", stdin); speed(); solve(); return 0; }

Compilation message (stderr)

arboras.cpp: In function 'void build_chain()':
arboras.cpp:83:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   83 |         for (int i = 0; i < ver.size(); i ++)
      |                         ~~^~~~~~~~~~~~
arboras.cpp: In function 'void update_edge(int, ll)':
arboras.cpp:361:33: warning: variable 'sad' set but not used [-Wunused-but-set-variable]
  361 |                 pair < ll, ll > sad = get_element(par[v]);
      |                                 ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...