This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/**
* user: loginov-0a5
* fname: Igor
* lname: Loginov
* task: Arboras
* score: 100.0
* date: 2020-12-04 12:01:41.831192
*/
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 1e9 + 7;
const int N = 101000;
int n;
int et[N], T;
vector<vector<pair<int, long long> > > g;
void dfs0(int v)
{
et[v] = T++;
for (auto u : g[v]) dfs0(u.first);
}
int p[N];
long long len[N];
int id[N];
long long d2[N];
int children[N]; // next vertex in the path
int path_id[N]; // where vertex V is located (probably, HLD is needed)
vector<int> path_root; // root of each path
int depth[N]; // distance from root to V in edges
//long long h[N]; // distance from root to V in metres (segment tree)
long long cur1, cur2; // current answers
long long go[N]; // longest path from V in metres, path_root[path_id[V]] == V must holds
long long tree1[4 * N];
long long push1[4 * N];
void Push1(int V)
{
push1[2 * V + 1] += push1[V];
push1[2 * V + 2] += push1[V];
tree1[2 * V + 1] += push1[V];
tree1[2 * V + 2] += push1[V];
push1[V] = 0;
}
long long geth(int pos, int L = 0, int R = N, int V = 0)
{
if (L + 1 == R)
{
return tree1[V];
}
Push1(V);
int M = (L + R) / 2;
if (pos < M) return geth(pos, L, M, 2 * V + 1);
else return geth(pos, M, R, 2 * V + 2);
}
void addh(int l, int r, long long x, int L = 0, int R = N, int V = 0)
{
if (R <= l || r <= L) return;
if (l <= L && R <= r)
{
push1[V] += x;
tree1[V] += x;
return;
}
int M = (L + R) / 2;
Push1(V);
addh(l, r, x, L, M, 2 * V + 1);
addh(l, r, x, M, R, 2 * V + 2);
}
int lst[N];
void dfs(int v, int D, long long H)
{
depth[v] = D;
addh(v, v + 1, H);
long long fnd = 0, fnd2 = 0;
int mxid = -1;
lst[v] = v;
for (auto id : g[v])
{
int u = id.first;
long long w = id.second;
dfs(u, D + 1, H + w);
lst[v] = lst[u];
if (mxid == -1 || go[u] + w > fnd)
{
mxid = u;
fnd2 = fnd;
fnd = go[u] + w;
}
else if (go[u] + w > fnd2)
{
fnd2 = go[u] + w;
}
}
d2[v] = fnd2;
cur2 = (cur2 + fnd2) % MOD;
//cout << v << " " << mxid << endl;
if (mxid == -1)
{
path_id[v] = path_root.size();
path_root.push_back(v);
}
else
{
children[v] = mxid;
go[v] = go[mxid] + len[mxid];
path_id[v] = path_id[mxid];
path_root[path_id[mxid]] = v;
}
cur1 = (cur1 + go[v]) % MOD;
}
int get_root(int v)
{
return path_root[path_id[v]];
}
long long get_actual(int v) // returns correct value of go[v]
{
int P = get_root(v);
long long dist = geth(v) - geth(P);
return go[P] - dist;
}
void update(int v, long long length, int direction)
{
//cout << v << " " << length << " " << direction << endl;
if (path_id[direction] == path_id[v])
{
long long delta = length - get_actual(v);
long long P = get_root(v);
cur1 = (cur1 + (depth[v] - depth[P] + 1) * delta) % MOD;
go[P] += delta;
if (P != 0)
{
update(p[P], get_actual(P) + len[P], P);
}
}
else
{
long long we = get_actual(v);
if (we >= length)
{
if (length >= d2[v])
{
cur2 = (cur2 - d2[v] + length) % MOD;
d2[v] = length;
}
return;
}
int P = get_root(v);
cur2 = (cur2 - d2[v] + we) % MOD;
d2[v] = we;
int nid = path_id[direction];
go[children[v]] = get_actual(children[v]);
path_root[path_id[children[v]]] = children[v];
children[v] = direction;
//cout << children[v] << " " << direction << " " << get_root(v) << " " << P << endl;
{
int kek = v;
while (1)
{
path_id[kek] = nid;
if (kek == P) break;
kek = p[kek];
}
path_root[path_id[kek]] = kek;
}
long long delta = length - we;
cur1 = (cur1 + (depth[v] - depth[P] + 1) * delta) % MOD;
go[P] += delta;
if (P != 0)
{
update(p[P], get_actual(P) + len[P], P);
}
}
}
void ans()
{
long long A = cur1;
for (int i = 0; i < n; i++)
{
long long mx1 = 0, mx2 = 0;
for (auto id : g[i])
{
long long Len = get_actual(id.first) + len[id.first];
if (Len > mx1)
{
mx2 = mx1;
mx1 = Len;
}
else if (Len > mx2)
{
mx2 = Len;
}
}
A = (A + mx2) % MOD;
}
cout << A << "\n";
}
/*
5
0 0 1 1
0 0 0 0
10
1 2
2 2
3 2
4 2
4 1
3 1
2 1
1 1
4 1000
2 1000
7
0 1 1 3 3 4
100000000 100000000 100000000 100000000 100000000 100000000
10
5 1
4 3
6 5
1 1
3 10000000
5 1000000
3 4
1 100000000
4 1000000000
6 100000
7
0 1 1 3 3 4
10 10 10 10 10 10
6
5 1
4 1
6 1
1 1
3 100
5 100
8
0 0 2 0 2 4 3
0
*/
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> n;
g = vector<vector<pair<int, long long> > >(n);
for (int i = 1; i < n; i++)
{
cin >> p[i];
g[p[i]].push_back({i, 0});
}
dfs0(0);
vector<int> zz(n);
for (int i = 1; i < n; i++)
{
zz[i] = p[i];
}
for (int i = 1; i < n; i++)
{
p[et[i]] = et[zz[i]];
}
for (int i = 1; i < n; i++)
{
cin >> zz[i];
//zz[i] = 100000000 - i;
}
for (int i = 1; i < n; i++)
{
len[et[i]] = zz[i];
}
g = vector<vector<pair<int, long long> > >(n);
for (int i = 1; i < n; i++)
{
id[i] = g[p[i]].size();
g[p[i]].push_back({i, len[i]});
}
dfs(0, 0, 0);
/*
for (int i = 0; i < n; i++)
{
cout << get_actual(i) << " ";
}
cout << cur1 << "\n";
//*/
cout << (cur1 + cur2) % MOD << "\n";
int q;
cin >> q;
while (q--)
{
int v, add;
cin >> v >> add;
//v = rand() % n;
//add = 1;
v = et[v];
g[p[v]][id[v]].second += add;
long long g = get_actual(v);
len[v] += add;
//cout << v << " " << lst[v] << "\n";
addh(v, lst[v] + 1, add);
update(p[v], g + len[v], v);
/*
for (int j = 0; j < n; j++)
{
cout << path_id[j] << " ";
}
cout << "\n";
for (int j = 0; j < path_root.size(); j++)
{
cout << path_root[j] << " ";
}
cout << "\n";
for (int j = 0; j < n; j++)
{
cout << go[j] << " ";
}
cout << "\n";
for (int j = 0; j < n; j++)
{
cout << geth(j) << " ";
}
cout << "\n";
//*/
/*
for (int j = 0; j < n; j++)
{
cout << get_actual(j) << " ";
}
cout << "\n";
cout << cur1 << "\n";
//*/
cout << (cur1 + cur2) % MOD << "\n";
//ans();
}
}
# | 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... |