Problem:
Do It Yourself?
You are the head of a group of $n$ employees including you in a company. Each employee has an employee ID, which is an integer 1 through n, where your ID is 1. Employees are often called by their IDs for short: #1, #2, and so on. Every employee other than you has a unique
immediate boss
, whose ID is smaller than his/hers. A boss of an employee is transitively defined as follows.
If an employee #$i$ is the immediate boss of an employee #$j$, then #$i$ is a boss of #$j$.
If #$i$ is a boss of #$j$ and #$j$ is a boss of #$k$, then #$i$ is a boss of #$k$.
Every employee including you is initially assigned exactly one task. That task can be done by him/herself or by any one of his/her bosses. Each employee can do an arbitrary number of tasks, but doing many tasks makes the employee too tired. Formally, each employee #$i$ has an individual fatigability constant $f_i$ , and if #$i$ does $m$ tasks in total, then the fatigue level of #$i$ will become $f_i \times m^2$.
Your mission is to minimize the sum of fatigue levels of all the $n$ employees.
Input
The input consists of a single test case in the following format.
$n$
$b_2$ $b_3$ ... $b_n$
$f_1$ $f_2$ ... $f_n$
The integer $n$ in the first line is the number of employees, where $2 \leq n \leq 5 \times 10^5$. The second line has $n - 1$ integers $b_i$ ($2 \leq i \leq n$), each of which represents the immediate boss of the employee #$i$, where $1 \leq b_i < i$. The third line has $n$ integers $f_i$ ($1 \leq i \leq n$), each of which is the fatigability constant of the employee #$i$, where $1 \leq f_i \leq 10^{12}$.
Output
Output the minimum possible sum of fatigue levels of all the $n$ employees.
Sample Input 1
4
1 1 2
1 1 1 1
Sample Output 1
4
Sample Input 2
4
1 1 2
1 10 10 10
Sample Output 2
16
Sample Input 3
4
1 1 2
1 2 4 8
Sample Output 3
10
Figure J.1. Illustration of the three samples (from left to right)
The situations and solutions of the three samples are illustrated in Figure J.1.
For Sample Input 1, the unique optimal way is that each employee does his/her task by him/her-self. That is, you should just say “Do it yourself!” to everyone.
For Sample Input 2, the unique optimal way is that the employee #1 does all the tasks. That is, you should just say “Leave it to me!” to everyone.
For Sample Input 3, one of the optimal ways is the following.
#1 does the tasks of #1 and #2, and then the fatigue level of #1 will be $1 \times 2^2 = 4$.
#2 does the task of #4, and then the fatigue level of #2 will be $2 \times 1^2 = 2$.
#3 does the initially assigned task, and then the fatigue level of #3 will be $4 \times 1^2 = 4$.
#4 does nothing, and then the fatigue level of #4 will be $8 \times 0^2 = 0$.
Thus, the sum of the fatigue levels is $4 + 2 + 4 + 0 = 10$. There is another optimal way, in which the employees #1, #2, and #3 do their initially assigned tasks by themselves and #1 does the task of #4 in addition.

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) begin(v), end(v)
using ll = long long;
multiset<ll> st[500010];
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<int> p(n);
    vector<vector<int>> g(n);
    for (int i = 1; i < n; i++) {
        cin >> p[i];
        p[i]--;
        g[p[i]].push_back(i);
    }
    vector<ll> f(n);
    rep(i, n) cin >> f[i];
    for (int i = n - 1; i >= 0; i--) {
        ll cur = f[i];
        st[i].insert(cur);
        cur += f[i] * 2;
        while (*st[i].rbegin() > cur) {
            st[i].erase(prev(st[i].end()));
            st[i].insert(cur);
            cur += f[i] * 2;
        }
        if(i==0)break;
        if (st[i].size() > st[p[i]].size()) swap(st[p[i]], st[i]);
        for (ll x : st[i]) st[p[i]].insert(x);
        st[i].clear();
    }
    ll ans = 0;
    for (ll x : st[0]) ans += x;
    cout << ans << endl;
}
accuracy: 1
time_ms: 1800
memory_kb: 94904
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i, n) for (ll i=0; i<ll(n); i++)
template <class T> using V = vector<T>;
template<class A, class B>
bool chmax(A &a, B b) { return a < b && (a = b, true); }
template<class A, class B>
bool chmin(A &a, B b) { return b < a && (a = b, true); }

template <class S, S op(S, S)>
struct Segtree {
  int n, s;
  S e;
  V<S> d;
  Segtree() = default;
  Segtree(unsigned n, S e) : n(n), s(bit_ceil(n)), e(e) {
    d.assign(2 * s, e);
  }
  Segtree(const vector<S>& v, S e) : Segtree(v.size(), e) {
    ranges::copy(v, d.begin() + s);
    for (int i = s - 1; i >= 1; i--)
      d[i] = op(d[2 * i], d[2 * i + 1]);
  }
  void set(int p, S x) {
    d[p += s] = x;
    while ((p >>= 1) >= 1)
      d[p] = op(d[2 * p], d[2 * p + 1]);
  }
  S get(int p) {
    return d[p + s];
  }
  S prod(int l, int r) {
    S sml = e, smr = e;
    l += s, r += s;
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1, r >>= 1;
    }
    return op(sml, smr);
  }
  template <class G>
  int max_right(int l, G f) {
    if (l == n) return n;
    l += s;
    S sm = e;
    while (1) {
      while (l % 2 == 0) l >>= 1;
      S t = op(sm, d[l]);
      if (!f(t)) break;
      sm = t;
      if (l++, (l & -l) == l) return n;
    }
    while (l < s) {
      l = 2 * l;
      if (S t = op(sm, d[l]); f(t)) sm = t, l++;
    }
    return l - s;
  }
  template <class F>
  int min_left(int r, F f) {
    if (r == 0) return 0;
    r += s;
    S sm = e;
    while (1) {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      S t = op(d[r], sm);
      if (!f(t)) break;
      sm = t;
      if ((r & -r) == r) return 0;
    }
    while (r < s) {
      r = 2 * r + 1;
      if (S t = op(d[r], sm); f(t)) sm = t, r--;
    }
    return r + 1 - s;
  }
};

template <class S, class F, S op(S, S),
          F composition(F, F), S mapping(F, S)>
struct LazySegtree {
  int n, s, log;
  S e;
  F id;
  V<S> d;
  V<F> lz;

  void update(int k) {
    d[k] = op(d[2 * k], d[2 * k + 1]);
  }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < s) lz[k] = composition(f, lz[k]);
    // if(d[k].fail) push(k), update(k);
  }
  void push(int k) {
    all_apply(2 * k, lz[k]);
    all_apply(2 * k + 1, lz[k]);
    lz[k] = id;
  }
  
  LazySegtree() = default;
  LazySegtree(unsigned n, S e, F id)
      : n(n), s(bit_ceil(n)), e(e), id(id) {
    log = countr_zero((unsigned)s);
    d.assign(2 * s, e), lz.assign(s, id);
  }
  LazySegtree(const vector<S>& v, S e, F id)
      : LazySegtree(v.size(), e, id) {
    ranges::copy(v, d.begin() + s);
    for (int i = s - 1; i >= 1; i--) update(i);
  }
  void set(int p, S x) {
    p += s;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = x;
    for (int i = 1; i <= log; i++) update(p >> i);
  }
  S get(int p) {
    p += s;
    for (int i = log; i >= 1; i--) push(p >> i);
    return d[p];
  }
  S prod(int l, int r) {
    if (l == r) return e;
    l += s, r += s;
    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }
    S sml = e, smr = e;
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1, r >>= 1;
    }
    return op(sml, smr);
  }
  void apply(int l, int r, F f) {
    if (l == r) return;
    l += s, r += s;
    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }
    {
      int l2 = l, r2 = r;
      while (l < r) {
        if (l & 1) all_apply(l++, f);
        if (r & 1) all_apply(--r, f);
        l >>= 1, r >>= 1;
      }
      l = l2, r = r2;
    }
    for (int i = 1; i <= log; i++) {
      if (((l >> i) << i) != l) update(l >> i);
      if (((r >> i) << i) != r) update((r - 1) >> i);
    }
  }
  template <class G>
  int max_right(int l, G g) {
    if (l == n) return n;
    l += s;
    for (int i = log; i >= 1; i--) push(l >> i);
    S sm = e;
    do {
      while (l % 2 == 0) l >>= 1;
      if (!g(op(sm, d[l]))) {
        while (l < s) {
          push(l);
          l = 2 * l;
          if (g(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - s;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return n;
  }
  template <bool (*g)(S)>
  int min_left(int r) {
    return min_left(r, [](S x) { return g(x); });
  }
  template <class G>
  int min_left(int r, G g) {
    if (r == 0) return 0;
    r += s;
    for (int i = log; i >= 1; i--) push((r - 1) >> i);
    S sm = e;
    do {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      if (!g(op(d[r], sm))) {
        while (r < s) {
          push(r);
          r = 2 * r + 1;
          if (g(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - s;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }
};

struct HLD {
  int N;
  int g;
  V<V<int>> t;
  V<int> par, dep, sz, pp, stov, vtos, px, index;
  HLD(int N, V<V<int>> graph, int root)
      : N(N), g(0), t(move(graph)), par(N, -1),
      dep(N), sz(N, 1), pp(N), stov(N), vtos(N),
      px(N), index(N) {
    dfs1(root);
    dfs2(root);
  }
  void dfs1(int v) {
    for (auto& w : t[v]){
      t[w].erase(find(t[w].begin(), t[w].end(), v));
      par[w] = v;
      dep[w] = dep[v] + 1;
      dfs1(w);
      sz[v] += sz[w];
      if(sz[t[v][0]] < sz[w]) swap(t[v][0], w);
    }
  }
  void dfs2(int v) {
    vtos[v] = g;
    stov[g++] = v;
    for (auto w : t[v]){
      int f = w == t[v][0];
      pp[w] = f ? pp[v] : w;
      px[w] = px[v] + 1 - f;
      dfs2(w);
    }
  }
  int lca(int a, int b) {
    if (px[pp[a]] > px[pp[b]]) swap(a, b);
    while (px[pp[a]] < px[pp[b]]) b = par[pp[b]];
    while (pp[a] != pp[b]) {
      a = par[pp[a]];
      b = par[pp[b]];
    }
    return dep[a] < dep[b] ? a : b;
  }
  auto query_half(int r, int a, bool edge = false) {
    vector<pair<int,int>> res(px[a] - px[r] + 1);
    while (px[a] > px[r]) {
      res[px[a] - px[r]] = { vtos[pp[a]], vtos[a] + 1 };
      a = par[pp[a]];
    }
    res[0] = { vtos[r] + edge, vtos[a] + 1 };
    return res;
  }
  // return vector<pair<int,int>>
  // a -> b
  // l<r縺ｪ繧閏l:r)縲〕>r縺ｪ繧閏r:l)縺ｮ騾・・  // edge=true縺ｮ蝣ｴ蜷医・lca繧貞性縺ｾ縺ｪ縺・玄髢薙ｒ霑斐☆
  auto query(int a, int b, bool edge = false) {
    int g = lca(a, b);
    auto l = query_half(g, b, edge);
    auto r = query_half(g, a, 1);
    for(auto& q : r) swap(q.first, q.second);
    l.insert(l.begin(), r.rbegin(), r.rend());
    return l;
  }
  // 霑斐ｊ蛟､縺ｯ邵ｮ邏・ｾ後・邵ｮ邏・ｾ後・鬆らせ髮・粋 vector<int> 縺ｨ
  // 譛ｨ縺ｮ霎ｺ縺ｮ髮・粋 vector<pair<int,int>> !! 繧ゅ→縺ｮ鬆らせ逡ｪ蜿ｷ !!
  // 繧ゅ＠ reindex 縺励◆縺・↑繧・index[v] 繧定ｦ九ｌ縺ｰ縺・＞
  pair<V<int>, V<pair<int, int>>> ComputeTree(V<int> vs) {
    auto comp = [&](int x, int y) { return vtos[x] < vtos[y]; };
    sort(vs.begin(), vs.end(), comp);
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    int K = vs.size();
    REP(i, K - 1) vs.push_back(lca(vs[i], vs[i + 1]));
    sort(vs.begin(), vs.end(), comp);
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    K = vs.size();
    REP(i, K) index[vs[i]] = i;
    V<pair<int, int>> es;
    REP(i, K - 1) {
      int p = lca(vs[i], vs[i + 1]);
      es.push_back({ vs[i + 1], p });
    }
    return {vs, es};
  }
};

ll sum(ll a, ll b) { return a+b; }
ll minll(ll a, ll b) { return min(a, b); }

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int n; cin >> n;
    V<V<int>> g(n);
    for(int i = 1; i < n; i++) {
        int b; cin >> b; b--;
        g[i].push_back(b);
        g[b].push_back(i);
    }
    HLD hld(n, g, 0);
    V<ll> f(n);
    REP(i, n) cin >> f[i];
    using P = pair<ll, int>;
    priority_queue<P, V<P>, greater<P>> pq;
    REP(i, n) {
        pq.emplace(f[i], i);
    }
    // [0,1,3],[2]
    // 4,2,1,1
    // 4,-2,-1,0,-1
    // 3,-1,-1,0,-1
    // 3,2,1,1
    V<ll> sz(n);
    REP(i, n) sz[hld.vtos[i]] = hld.sz[i];
    LazySegtree<ll, ll, minll, sum, sum> seg(sz, INF, 0LL);
    ll ans = 0;
    REP(i, n) {
        auto affordable = [&](int u) {
            for(auto [l, r] : hld.query(0, u)) {
                if(l > r) swap(l, r);
                if(seg.prod(l, r) <= 0LL) return false;
            }
            return true;
        };
        while(!pq.empty() && !affordable(pq.top().second)) pq.pop();
        auto [v, u] = pq.top(); pq.pop();
        ans += v;
        pq.emplace(v + f[u]*2, u);
        for(auto [l, r] : hld.query(0, u)) {
            if(l > r) swap(l, r);
            seg.apply(l, r, -1LL);
        }
    }
    cout << ans << '\n';
}
accuracy: 1
time_ms: 2000
memory_kb: 140852
final_rank: 13

code_snippet: // AOJ #1453 Do It Yourself?
// 2025.5.1

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

ll Cinll() {
	ll n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

struct SegTree {
    int n;
    vector<ll> mn, lz;
    SegTree(int _n): n(_n), mn(4*n), lz(4*n,0) {}
    void apply(int i, ll v) { mn[i] += v, lz[i] += v; }
    void push(int i) {
        if (lz[i]) {
            apply(i<<1, lz[i]);
            apply(i<<1|1, lz[i]);
            lz[i] = 0;
        }
    }
    void build(int i, int l, int r, const vector<ll> &a) {
        if (l == r) mn[i] = a[l];
        else {
            int m = (l+r)>>1;
            build(i<<1, l, m, a);
            build(i<<1|1, m+1, r, a);
            mn[i] = min(mn[i<<1], mn[i<<1|1]);
        }
    }
    void update(int i, int l, int r, int ql, int qr, ll v) {
        if (qr < l || r < ql) return;
        if (ql <= l && r <= qr) {
            apply(i, v);
            return;
        }
        push(i);
        int m = (l+r)>>1;
        update(i<<1, l, m, ql, qr, v);
        update(i<<1|1, m+1, r, ql, qr, v);
        mn[i] = min(mn[i<<1], mn[i<<1|1]);
    }
    ll query(int i, int l, int r, int ql, int qr) {
        if (qr < l || r < ql) return LLONG_MAX;
        if (ql <= l && r <= qr) return mn[i];
        push(i);
        int m = (l+r)>>1;
        return min(query(i<<1, l, m, ql, qr), query(i<<1|1, m+1, r, ql, qr));
    }
    void build(const vector<ll> &a) { build(1,0,n-1,a); }
    void update(int l, int r, ll v) { update(1,0,n-1,l,r,v); }
    ll query(int l, int r) { return query(1,0,n-1,l,r); }
};

int main(){
    int n = Cin();
    vector<vector<int>> ch(n+1);
    vector<int> parent(n+1,0);
    for(int i=2;i<=n;i++){
        int b = Cin();
        parent[i] = b;
        ch[b].push_back(i);
    }
    vector<ll> f(n+1);
    for(int i=1;i<=n;i++) f[i] = Cinll();

    vector<int> stk = {1}, order;
    order.reserve(n);
    while(!stk.empty()){
        int u = stk.back(); stk.pop_back();
        order.push_back(u);
        for(int v: ch[u]) stk.push_back(v);
    }
    vector<int> sz(n+1,1), heavy(n+1,-1);
    for(int i=n-1; i>=0; i--){
        int u = order[i];
        int mx = 0;
        for(int v: ch[u]){
            sz[u] += sz[v];
            if(sz[v] > mx){
                mx = sz[v];
                heavy[u] = v;
            }
        }
    }

    vector<int> head(n+1), pos(n+1);
    head[1] = 1;
    int cur = 0;
    vector<pair<int,int>> st2;
    st2.reserve(n);
    st2.emplace_back(1,1);
    while(!st2.empty()){
        auto [u,h] = st2.back(); st2.pop_back();
        int v = u;
        while(v != -1){
            head[v] = h;
            pos[v] = cur++;
            for(int w: ch[v]){
                if(w != heavy[v]) st2.emplace_back(w, w);
            }
            v = heavy[v];
        }
    }

    vector<ll> arr(n);
    for(int u=1;u<=n;u++) arr[pos[u]] = sz[u];
    SegTree st(n);
    st.build(arr);

    struct E { ll cost; int u, k; };
    struct Cmp { bool operator()(E const&a, E const&b) const {
        return a.cost > b.cost;
    }};
    priority_queue<E, vector<E>, Cmp> pq;
    for(int u=1; u<=n; u++) pq.push({ f[u], u, 1 });

    __int128 ans = 0;
    int taken = 0;
    while(taken < n){
        auto e = pq.top(); pq.pop();
        ll c = e.cost;
        int u = e.u, k = e.k;

        bool ok = true;
        int v = u;
        while(v){
            int h = head[v];
            if(st.query(pos[h], pos[v]) <= 0){
                ok = false;
                break;
            }
            v = parent[h];
        }
        if(!ok) continue;

        ans += c;
        taken++;
        v = u;
        while(v){
            int h = head[v];
            st.update(pos[h], pos[v], -1);
            v = parent[h];
        }
        if(k < sz[u]){
            ll nc = f[u] * (2LL*(k+1) - 1);
            pq.push({ nc, u, k+1 });
        }
    }

    if(ans == 0) cout << 0 << endl;
    else {
        string s;
        while(ans > 0){
            s.push_back(char('0' + ans % 10));
            ans /= 10;
        }
        reverse(s.begin(), s.end());
        cout << s << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 1580
memory_kb: 91056
final_rank: 7

code_snippet: #include<iostream>
#include<string>
#include<utility>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
using ll= long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)
#define repr(i,n) for(ll i=(n)-1; i>=0; i--)
template<class T> void chmin(T& l, T r){ if(r < l) l = r; }
template<class T> void chmax(T& l, T r){ if(l < r) l = r; }


struct FenwickTree{
    int N;
    vector<int> A;
    FenwickTree(int n = 1){
        N = n;
        A.assign(N+1, 0);
    }
    int sum(int r){
        int x = 0;
        while(r > 0){ x += A[r]; r -= r&-r; }
        return x;
    }
    int sum(int l, int r){
        return sum(r) - sum(l);
    }
    void add(int p, int x){
        p++;
        while(p <= N){
            A[p] += x;
            p += p & -p;
        }
    }
};

struct Segtree{
    int N;
    vector<int> A;
    vector<int> F;
    int shN;
    Segtree(int n, int INF){
        N = 1; shN = 0; while(N < n){ shN++; N *= 2; }
        A.assign(N*2, INF);
        F.assign(N*2, 0);
    }
    void agg(int i){
        if(i < N) A[i] = min(A[i*2], A[i*2+1]);
    }
    void set(int p, int x){
        p += N;
        A[p] = x;
        while(p > 1){ agg(p/=2); }
    }
    void appnode(int i, int f){
        A[i] += f; F[i] += f;
    }
    void prop(int p){
        if(p >= N) return;
        appnode(p*2, F[p]);
        appnode(p*2+1, F[p]);
        F[p] = 0;
    }
    void propto(int p){
        p += N;
        repr(sh,shN+1) prop(p >> sh);
    }
    int prod(int l, int r){
        if(l) propto(l-1);
        if(r != N) propto(r);
        l += N; r += N;
        int res = A[0];
        while(l < r){
            if(l%2) chmin(res, A[l++]);
            if(r%2) chmin(res, A[--r]);
            l /= 2; r /= 2;
        }
        return res;
    }
    void apply(int l, int r, int f, int a=-1, int b=-1, int i=-1){
        if(i<0){ i = 1; a = 0; b = N; }
        if(l <= a && b <= r){ appnode(i,f); return; }
        if(r <= a || b <= l) return;
        prop(i);
        apply(l,r,f,a,(a+b)/2,i*2);
        apply(l,r,f,(a+b)/2,b,i*2+1);
        agg(i);
    }
};



void testcase(){
    ll N; cin >> N;
    vector<int> B(N,-1);
    for(int i=1; i<N; i++){ int p; cin >> p; p--; B[i] = p; }
    vector<ll> F(N); rep(i,N) cin >> F[i];
    vector<int> R(N);
    vector<int> PP(N);
    {
        vector<vector<int>> child(N);
        rep(i,N) if(i) child[B[i]].push_back(i);
        vector<int> sz(N, 1);
        repr(i,N) if(i) sz[B[i]] += sz[i];
        rep(i,N) sort(child[i].begin(), child[i].end(),
            [&](int l, int r){ return sz[l] > sz[r]; });
        vector<int> newidx(N);
        rep(i,N){
            int chi = newidx[i] + 1;
            if(child[i].size()) PP[chi] = PP[chi-1];
            for(int c : child[i]){
                if(c != child[i][0]) PP[chi] = chi;
                newidx[c] = chi;
                chi += sz[c];
            }
        }
        //rep(i,N) cout << newidx[i] << " ";
        //cout << endl;
        vector<ll> nF(N);
        rep(i,N) nF[newidx[i]] = F[i];
        vector<int> nB(N,-1);
        rep(i,N) if(i) nB[newidx[i]] = newidx[B[i]];
        rep(i,N) R[newidx[i]] = newidx[i] + sz[i];
        swap(F, nF); swap(B, nB);
    }
    //rep(i,N) cout << R[i] << " ";
    //cout << endl;
    //rep(i,N) cout << F[i] << " ";
    //cout << endl;
    //rep(i,N) cout << B[i] << " ";
    //cout << endl;
    Segtree sg(N, 1001001001);
    rep(i,N) sg.set(i, R[i]-i);
    auto pathmin = [&](int v) -> int {
        int res = 1;
        while(v >= 0){
            chmin(res, sg.prod(PP[v], v+1));
            v = B[PP[v]];
        }
        return res;
    };
    auto pathdec = [&](int v) -> void {
        while(v >= 0){
            sg.apply(PP[v], v+1, -1);
            v = B[PP[v]];
        }
    };
    vector<ll> cnt(N);
    FenwickTree C(N+1);
    FenwickTree D(N);
    priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> que;
    ll ans = 0;
    auto up = [&](int p) -> void {
        ans += (cnt[p] * 2 + 1) * F[p];
        cnt[p]++;
        pathdec(p);
        que.push({ (cnt[p] * 2 + 1) * F[p], p });
    };
    rep(i,N) que.push({ F[i], i });
    while(que.size()){
        auto [f, p] = que.top(); que.pop();
        if(pathmin(p) <= 0) continue;
        //cout << "f = " << f << " , p = " << p << endl;
        up(p);
    }
    cout << ans << "\n";
}


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 2120
memory_kb: 51236
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<utility>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
using ll= long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)
#define repr(i,n) for(ll i=(n)-1; i>=0; i--)
template<class T> void chmin(T& l, T r){ if(r < l) l = r; }
template<class T> void chmax(T& l, T r){ if(l < r) l = r; }


struct FenwickTree{
    int N;
    vector<int> A;
    FenwickTree(int n = 1){
        N = n;
        A.assign(N+1, 0);
    }
    int sum(int r){
        int x = 0;
        while(r > 0){ x += A[r]; r -= r&-r; }
        return x;
    }
    int sum(int l, int r){
        return sum(r) - sum(l);
    }
    void add(int p, int x){
        p++;
        while(p <= N){
            A[p] += x;
            p += p & -p;
        }
    }
};

struct Segtree{
    int N;
    vector<int> A;
    vector<int> F;
    int shN;
    Segtree(int n, int INF){
        N = 1; shN = 0; while(N < n){ shN++; N *= 2; }
        A.assign(N*2, INF);
        F.assign(N*2, 0);
    }
    void agg(int i){
        if(i < N) A[i] = min(A[i*2], A[i*2+1]);
    }
    void set(int p, int x){
        p += N;
        A[p] = x;
        while(p > 1){ agg(p/=2); }
    }
    void appnode(int i, int f){
        A[i] += f; F[i] += f;
    }
    void prop(int p){
        if(p >= N) return;
        appnode(p*2, F[p]);
        appnode(p*2+1, F[p]);
        F[p] = 0;
    }
    void propto(int p){
        p += N;
        repr(sh,shN+1) prop(p >> sh);
    }
    int prod(int l, int r){
        if(l) propto(l-1);
        if(r != N) propto(r);
        l += N; r += N;
        int res = A[0];
        while(l < r){
            if(l%2) chmin(res, A[l++]);
            if(r%2) chmin(res, A[--r]);
            l /= 2; r /= 2;
        }
        return res;
    }
    void apply(int l, int r, int f, int a=-1, int b=-1, int i=-1){
        if(i<0){ i = 1; a = 0; b = N; }
        if(l <= a && b <= r){ appnode(i,f); return; }
        if(r <= a || b <= l) return;
        prop(i);
        apply(l,r,f,a,(a+b)/2,i*2);
        apply(l,r,f,(a+b)/2,b,i*2+1);
        agg(i);
    }
};



void testcase(){
    ll N; cin >> N;
    vector<int> B(N,-1);
    for(int i=1; i<N; i++){ int p; cin >> p; p--; B[i] = p; }
    vector<ll> F(N); rep(i,N) cin >> F[i];
    vector<int> R(N);
    vector<int> PP(N);
    {
        vector<vector<int>> child(N);
        rep(i,N) if(i) child[B[i]].push_back(i);
        vector<int> sz(N, 1);
        repr(i,N) if(i) sz[B[i]] += sz[i];
        rep(i,N) sort(child[i].begin(), child[i].end(),
            [&](int l, int r){ return sz[l] > sz[r]; });
        vector<int> newidx(N);
        rep(i,N){
            int chi = newidx[i] + 1;
            if(child[i].size()) PP[chi] = PP[chi-1];
            for(int c : child[i]){
                if(c != child[i][0]) PP[chi] = chi;
                newidx[c] = chi;
                chi += sz[c];
            }
        }
        //rep(i,N) cout << newidx[i] << " ";
        //cout << endl;
        vector<ll> nF(N);
        rep(i,N) nF[newidx[i]] = F[i];
        vector<int> nB(N,-1);
        rep(i,N) if(i) nB[newidx[i]] = newidx[B[i]];
        rep(i,N) R[newidx[i]] = newidx[i] + sz[i];
        swap(F, nF); swap(B, nB);
    }
    //rep(i,N) cout << R[i] << " ";
    //cout << endl;
    //rep(i,N) cout << F[i] << " ";
    //cout << endl;
    //rep(i,N) cout << B[i] << " ";
    //cout << endl;
    Segtree sg(N, 1001001001);
    rep(i,N) sg.set(i, R[i]-i);
    auto pathmin = [&](int v) -> int {
        int res = 1;
        while(v >= 0){
            chmin(res, sg.prod(PP[v], v+1));
            v = B[PP[v]];
        }
        return res;
    };
    auto pathdec = [&](int v) -> void {
        while(v >= 0){
            sg.apply(PP[v], v+1, -1);
            v = B[PP[v]];
        }
    };
    vector<ll> cnt(N);
    FenwickTree C(N+1);
    FenwickTree D(N);
    priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> que;
    ll ans = 0;
    auto up = [&](int p) -> void {
        ans += (cnt[p] * 2 + 1) * F[p];
        cnt[p]++;
        pathdec(p);
        que.push({ (cnt[p] * 2 + 1) * F[p], p });
    };
    rep(i,N) que.push({ F[i], i });
    while(que.size()){
        auto [f, p] = que.top(); que.pop();
        if(pathmin(p) <= 0) continue;
        //cout << "f = " << f << " , p = " << p << endl;
        up(p);
    }
    cout << ans << "\n";
}


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 2130
memory_kb: 51668
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;


// base: 918715
unsigned int bit_ceil(unsigned int n) {
   unsigned int x = 1;
   while(x < (unsigned int)(n)) x *= 2;
   return x;
}
int countr_zero(unsigned int n) { return __builtin_ctz(n); }
constexpr int countr_zero_constexpr(unsigned int n) {
   int x = 0;
   while(!(n & (1 << x))) x++;
   return x;
}
template<class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
struct lazy_segtree {
   public:
   lazy_segtree() : lazy_segtree(0) {}
   explicit lazy_segtree(int n) : lazy_segtree(vector<S>(n, e())) {}
   explicit lazy_segtree(const vector<S>& v) : _n(int(v.size())) {
      size = (int)bit_ceil((unsigned int)(_n));
      log = countr_zero((unsigned int)size);
      d = vector<S>(2 * size, e());
      lz = vector<F>(size, id());
      for(int i = 0; i < _n; i++) d[size + i] = v[i];
      for(int i = size - 1; i >= 1; i--) { update(i); }
   }
   void set(int p, S x) {
      // assert(0 <= p && p < _n);
      p += size;
      for(int i = log; i >= 1; i--) push(p >> i);
      d[p] = x;
      for(int i = 1; i <= log; i++) update(p >> i);
   }

   S get(int p) {
      // assert(0 <= p && p < _n);
      p += size;
      for(int i = log; i >= 1; i--) push(p >> i);
      return d[p];
   }

   S prod(int l, int r) {
      // assert(0 <= l && l <= r && r <= _n);
      if(l == r) return e();

      l += size;
      r += size;

      for(int i = log; i >= 1; i--) {
         if(((l >> i) << i) != l) push(l >> i);
         if(((r >> i) << i) != r) push((r - 1) >> i);
      }

      S sml = e(), smr = e();
      while(l < r) {
         if(l & 1) sml = op(sml, d[l++]);
         if(r & 1) smr = op(d[--r], smr);
         l >>= 1;
         r >>= 1;
      }

      return op(sml, smr);
   }

   void apply(int l, int r, F f) {
      assert(0 <= l && l <= r && r <= _n);
      if(l == r) return;

      l += size;
      r += size;

      for(int i = log; i >= 1; i--) {
         if(((l >> i) << i) != l) push(l >> i);
         if(((r >> i) << i) != r) push((r - 1) >> i);
      }

      {
         int l2 = l, r2 = r;
         while(l < r) {
            if(l & 1) all_apply(l++, f);
            if(r & 1) all_apply(--r, f);
            l >>= 1;
            r >>= 1;
         }
         l = l2;
         r = r2;
      }

      for(int i = 1; i <= log; i++) {
         if(((l >> i) << i) != l) update(l >> i);
         if(((r >> i) << i) != r) update((r - 1) >> i);
      }
   }

   template<class G> int max_right(int l, G g) {
      // assert(0 <= l && l <= _n);
      // assert(g(e()));
      if(l == _n) return _n;
      l += size;
      for(int i = log; i >= 1; i--) push(l >> i);
      S sm = e();
      do {
         while(l % 2 == 0) l >>= 1;
         if(!g(op(sm, d[l]))) {
            while(l < size) {
               push(l);
               l = (2 * l);
               if(g(op(sm, d[l]))) {
                  sm = op(sm, d[l]);
                  l++;
               }
            }
            return l - size;
         }
         sm = op(sm, d[l]);
         l++;
      } while((l & -l) != l);
      return _n;
   }  // d93691

   template<class G> int min_left(int r, G g) {
      // assert(0 <= r && r <= _n);
      // assert(g(e()));
      if(r == 0) return 0;
      r += size;
      for(int i = log; i >= 1; i--) push((r - 1) >> i);
      S sm = e();
      do {
         r--;
         while(r > 1 && (r % 2)) r >>= 1;
         if(!g(op(d[r], sm))) {
            while(r < size) {
               push(r);
               r = (2 * r + 1);
               if(g(op(d[r], sm))) {
                  sm = op(d[r], sm);
                  r--;
               }
            }
            return r + 1 - size;
         }
         sm = op(d[r], sm);
      } while((r & -r) != r);
      return 0;
   }  // c9a7eb

   private:
   int _n, size, log;
   vector<S> d;
   vector<F> lz;

   void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
   void all_apply(int k, F f) {
      d[k] = mapping(f, d[k]);
      if(k < size) lz[k] = composition(f, lz[k]);
   }
   void push(int k) {
      all_apply(2 * k, lz[k]);
      all_apply(2 * k + 1, lz[k]);
      lz[k] = id();
   }
};

class HLDcomposition {
   private:
   int V;
   vector<vector<int>> G;
   vector<int> stsize, parent, pathtop, in, out;
   int root;
   void build_stsize(int u, int p) {
      stsize[u] = 1, parent[u] = p;
      for(auto&& v : G[u]) {
         if(v == p) {
            if(v == G[u].back()) break;
            else swap(v, G[u].back());
         }
         build_stsize(v, u);
         stsize[u] += stsize[v];
         if(stsize[v] > stsize[G[u][0]]) swap(v, G[u][0]);
      }
   }

   void build_path(int u, int p, int& tm) {
      in[u] = tm++;
      for(auto v : G[u]) {
         if(v == p) continue;
         pathtop[v] = (v == G[u][0] ? pathtop[u] : v);
         build_path(v, u, tm);
      }
      out[u] = tm;
   }

   public:
   void add_edge(int u, int v) {
      G[u].push_back(v);
      G[v].push_back(u);
   }

   void build(int _root = 0) {
      root = _root;
      int tm = 0;
      build_stsize(root, -1);
      pathtop[root] = root;
      build_path(root, -1, tm);
   }

   inline int index(int a) { return in[a]; }

   int lca(int a, int b) {
      int pa = pathtop[a], pb = pathtop[b];
      while(pa != pb) {
         if(in[pa] > in[pb]) {
            a = parent[pa], pa = pathtop[a];
         } else {
            b = parent[pb], pb = pathtop[b];
         }
      }
      if(in[a] > in[b]) swap(a, b);
      return a;
   }

   pair<int, int> subtree_query(int a) { return {in[a], out[a]}; }

   vector<tuple<int, int, bool>> path_query(int from, int to) {
      int pf = pathtop[from], pt = pathtop[to];
      using T = tuple<int, int, bool>;
      deque<T> front, back;
      while(pf != pt) {
         if(in[pf] > in[pt]) {
            front.push_back({in[pf], in[from] + 1, true});
            from = parent[pf], pf = pathtop[from];
         } else {
            back.push_front({in[pt], in[to] + 1, false});
            to = parent[pt], pt = pathtop[to];
         }
      }
      if(in[from] > in[to]) front.push_back({in[to], in[from] + 1, true});
      else front.push_back({in[from], in[to] + 1, false});
      vector<T> ret;
      while(!front.empty()) {
         ret.push_back(front.front());
         front.pop_front();
      }
      while(!back.empty()) {
         ret.push_back(back.front());
         back.pop_front();
      }
      return ret;
   }

   HLDcomposition(int node_size)
       : V(node_size), G(V), stsize(V, 0), parent(V, -1), pathtop(V, -1), in(V, -1), out(V, -1) {}
};

const int inf = (1 << 30);
int op(int a, int b) {return min(a, b);}
int e() {return inf;}
int mapping(int a, int b) {return a + b;}
int composition(int a, int b) {return a + b;}
int id() {return 0;}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    HLDcomposition hld(n);
    vector<vector<int>> v(n);
    rep(i, n - 1) {
        int x; cin >> x;
        x --;
        v[x].pb(i + 1);
        hld.add_edge(x, i + 1);
    }
    hld.build();

    vector<ll> a(n);
    rep(i, n) cin >> a[i];

    lazy_segtree<int, op, e, int, mapping, composition, id> seg(vector<int> (n, 0));
    vector<ll> state(n, 0);
    rep(i, n) {
        for(auto [l, r, f] : hld.path_query(0, i)) {
            seg.apply(l, r, 1);
        } 
    }
    using P = pair<ll, int>;
    priority_queue<P, vector<P>, greater<P> > pq;
    rep(i, n) {
        pq.push({a[i], i});
    }
    ll ans = 0;
    while(!pq.empty()) {
        auto [val, i] = pq.top();
        pq.pop();
        int Min = inf;
        for(auto [l, r, f] : hld.path_query(0, i)) {
            Min = min(Min, seg.prod(l, r));
        }
        if(Min == 0) continue;
        ans += val;
        for(auto [l, r, f] : hld.path_query(0, i)) {
            seg.apply(l, r, -1);
        }
        state[i] ++;
        pq.push({a[i] * (state[i] * 2 + 1), i});
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 3220
memory_kb: 131296
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pi;
typedef vector<ll> vi;
typedef vector<vi> vvi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(A) A.begin(),A.end()
template<class S,S(*op)(S,S),S(*e)(),class T,S(*mapping)(T,S),T(*composition)(T,T),T(*id)()>
struct lazy_segtree{
    private:
    size_t N,h;
    vector<S>seg;
    vector<T>laz;
    public:
    lazy_segtree(int _N){init(_N);}
    void init(int _N){
        N=1,h=0;
        while(N<_N)N<<=1,h++;
        seg.assign(2*N,e());
        laz.assign(2*N,id());
    }
    void set(int i,S x){
        assert(0<=i&&i<N);
        i+=N;
        for(int k=h;k>0;k--){
            int v=i>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        seg[i]=x;
        for(int v=i>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
    }
    S get(int i){
        assert(0<=i&&i<N);
        i+=N;
        for(int k=h;k>0;k--){
            int v=i>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=i>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
        return seg[i];
    }
    S prod(int l,int r){
        assert(0<=l&&l<=r&&r<=N);
        if(l==r)return e();
        l+=N;r+=N;
        for(int k=h;k>0;k--){
            int v=l>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=l>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
        for(int k=h;k>0;k--){
            int v=(r-1)>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=(r-1)>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
        S L=e(),R=e();
        while(l<r){
            if(l&1)L=op(L,seg[l]),l++;
            if(r&1)r--,R=op(seg[r],R);
            l>>=1;
            r>>=1;
        }
        return op(L,R);
    }
    void apply(int l,int r,T f){
        assert(0<=l&&l<=r&&r<=N);
        if(l==r)return;
        l+=N;r+=N;
        for(int k=h;k>0;k--){
            int v=l>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=l>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
        for(int k=h;k>0;k--){
            int v=(r-1)>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=(r-1)>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
        int _l=l,_r=r;
        while(l<r){
            if(l&1)laz[l]=composition(f,laz[l]),seg[l]=mapping(f,seg[l]),l++;
            if(r&1)r--,laz[r]=composition(f,laz[r]),seg[r]=mapping(f,seg[r]);
            l>>=1;
            r>>=1;
        }
        l=_l;r=_r;
        for(int k=h;k>0;k--){
            int v=l>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=l>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
        for(int k=h;k>0;k--){
            int v=(r-1)>>k;
            seg[2*v]=mapping(laz[v],seg[2*v]);
            seg[2*v+1]=mapping(laz[v],seg[2*v+1]);
            laz[2*v]=composition(laz[v],laz[2*v]);
            laz[2*v+1]=composition(laz[v],laz[2*v+1]);
            laz[v]=id();
        }
        for(int v=(r-1)>>1;v;v>>=1)seg[v]=op(seg[2*v],seg[2*v+1]);
    }
};
ll op(ll a,ll b){return min(a,b);}
ll e(){return 1e18;}
ll ma(ll f,ll x){return f+x;}
ll co(ll f,ll g){return f+g;}
ll id(){return 0;}
int main(){
    ll N;cin>>N;
    vi P(N),A(N);
    FOR(i,1,N){
        cin>>P[i];
        P[i]--;
    }
    REP(i,N)cin>>A[i];
    vvi E(N);
    FOR(i,1,N)E[P[i]].emplace_back(i);
    vi S(N,1);
    function<void(ll)>dfs=[&](ll v){
        for(auto u:E[v])dfs(u),S[v]+=S[u];
    };
    dfs(0);

    priority_queue<pi,vector<pi>,greater<pi>>Q;
    REP(i,N)Q.emplace(pi(A[i],i));
    vi C(N,1);

    lazy_segtree<ll,op,e,ll,ma,co,id>seg(N);
    vi top(N);
    function<void(ll)>hld=[&](ll v){
        if(E[v].empty())return;
        ll m=0,t=0;
        for(auto u:E[v])m=max(m,S[u]),top[u]=u;
        while(S[E[v][t]]!=m)t++;
        ll r=E[v][t];
        top[r]=top[v];
        for(auto u:E[v])hld(u);
    };
    hld(0);
    ll cnt=0;
    vi idx(N);
    REP(i,N)if(E[i].empty()){
        ll v=i;
        idx[v]=cnt++;
        while(v!=top[i]){
            v=P[v];
            idx[v]=cnt++;
        }
    }
    REP(i,N)seg.set(idx[i],S[i]);
    auto prod=[&](ll v){
        ll res=e();
        while(1){
            res=op(res,seg.prod(idx[v],idx[top[v]]+1));
            if(top[v]==0)return res;
            v=P[top[v]];
        }
    };
    auto apply=[&](ll v){
        while(1){
            seg.apply(idx[v],idx[top[v]]+1,-1);
            if(top[v]==0)return;
            v=P[top[v]];
        }
    };

    ll ans=0;
    while(!Q.empty()){
        auto[_,v]=Q.top();Q.pop();
        if(prod(v)==0)continue;
        apply(v);
        C[v]+=2;
        ans+=_;
        Q.emplace(pi(A[v]*C[v],v));
    }
    cout<<ans<<endl;
    return 0;
}
accuracy: 1
time_ms: 3230
memory_kb: 109912
final_rank: 16

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define rng(i, l, r) for(int i = int(l); i < int(r); i++)
#define rep(i, n) rng(i,0,n)
#define sz(v) int(v.size())
#define foa(s, v) for(auto& s : v)
#define all(v) v.begin(),v.end()


template<class T>
using pqmin = priority_queue<T, vector<T>, greater<T>>;

#ifdef LOCAL
#define debug(x) cerr << __LINE__ << ", " << #x << ": " << x << endl
#else
#define debug(x) void(0)
#endif


using S = ll;
using F = ll;

S op(S x, S y) {
    return min(x, y);
}

F composition(F f, F g) { return f + g; }

constexpr F id = 0LL;
constexpr S e = 1e18;

S mapping(F f, S s) {
    if (s == e) return e;
    return f + s;
}

struct node {
    node *l = nullptr, *r = nullptr;
    ll lo, hi;
    S val = e;
    F mapp = id;

    node(ll lw, ll h) : lo(lw), hi(h) {}

    ~node() {
        if (l) {
            delete l;
            delete r;
        }
    }

    void push() {
        if (!l) {
            ll mid = lo + (hi - lo) / 2;
            l = new node(lo, mid), r = new node(mid, hi);
        }
        if (mapp != id) l->apply(lo, hi, mapp), r->apply(lo, hi, mapp), mapp = id;
    }

    void apply(ll L, ll R, F f) {
        if (R <= lo || hi <= L) return;
        if (L <= lo && hi <= R) {
            mapp = composition(f, mapp);
            val = mapping(f, val);
            return;
        }
        push(), l->apply(L, R, f), r->apply(L, R, f);
        val = op(l->val, r->val);
    }

    S prod(ll L, ll R) {
        if (R <= lo || hi <= L) return e;
        if (L <= lo && hi <= R) return val;
        push();
        return op(l->prod(L, R), r->prod(L, R));
    }

    S get(ll idx) {
        return prod(idx, idx + 1);
    }

    S all_prod() { return val; }

    void set(ll pos, S s) {
        if (pos < lo || hi <= pos) return;
        if (lo + 1 == hi) mapp = id, val = s;
        else {
            push(), l->set(pos, s), r->set(pos, s);
            val = op(l->val, r->val);
        }
    }
};

using vi = vector<int>;

template<bool VALS_EDGES = false>
struct HLD {
    int N, tim = 0;
    vector<vi> adj;
    vi par, siz, depth, rt, pos;
    node *tree;

    HLD(vector<vi> adj_) : N(sz(adj_)), adj(adj_), par(N, -1), siz(N, 1), depth(N), rt(N), pos(N),
                           tree(new node(0, N)) {
        dfsSz(0);
        dfsHld(0);

        rep(i, N) {
            tree->set(pos[i], siz[i]);
        }
    }

    HLD() = default;

    void dfsSz(int v) {
        if (par[v] != -1) adj[v].erase(find(all(adj[v]), par[v]));
        for (int &u: adj[v]) {
            par[u] = v, depth[u] = depth[v] + 1;
            dfsSz(u);
            siz[v] += siz[u];
            if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
        }
    }

    void dfsHld(int v) {
        pos[v] = tim++;
        foa(u, adj[v]) {
            rt[u] = (u == adj[v][0] ? rt[v] : u);
            dfsHld(u);
        }
    }

    template<class B>
    void process(int u, int v, B ope) {
        for (; rt[u] != rt[v]; v = par[rt[v]]) {
            if (depth[rt[u]] > depth[rt[v]]) swap(u, v);
            ope(pos[rt[v]], pos[v] + 1);
        }
        if (depth[u] > depth[v]) swap(u, v);
        ope(pos[u] + VALS_EDGES, pos[v] + 1);
    }

    void add_path(int u, int v, ll val) {
        process(u, v, [&](int l, int r) -> void { tree->apply(l, r, val); });
    }

    ll get_min(int u, int v) {
        ll ret = e;
        process(u, v, [&](int l, int r) -> void { ret = op(ret, tree->prod(l, r)); });
        return ret;
    }
};

struct chker {
    HLD<false> h;

    chker(vector<int> par) {
        int n = sz(par);
        vector<vi> adj(n);
        rng(i, 1, n) {
            int j = par[i];
            if (j < 0 || i == j) continue;
            adj[i].push_back(j);
            adj[j].push_back(i);
        }
        h = HLD<false>(adj);
    }

    bool available(int idx) {
        return h.get_min(0, idx) > 0;
    }

    void use(int idx) {
        h.add_path(0, idx, -1);
    }

    void end_tree() {
        if (h.tree) delete h.tree;
    }
};

struct naive {
    vector<int> par, cap;

    naive(vector<int> p) : par(p), cap(sz(p), 1) {
        for (int i = sz(p) - 1; i >= 0; i--) {
            if (i) cap[par[i]] += cap[i];
        }
    }

    bool available(int idx) {
        if (!cap[idx]) return false;
        return !idx || available(par[idx]);
    }

    void use(int idx) {
        cap[idx]--;
        if (idx) use(par[idx]);
    }
};

template<class T>
ostream &operator<<(ostream &os, vector<T> v) {
    os << "{ ";
    foa(x, v) os << x << ", ";
    return os << "}";
}

void test_checker() {
    int n = rand() % 200 + 1;
    vector<int> par(n, -1);
    rng(i, 1, n) par[i] = rand() % i;
    chker c(par);
    naive nv(par);

    vector<int> remain(n);
    iota(all(remain), 0);

    while (remain.size()) {
        int pos = rand() % sz(remain);
        int v = remain[pos];

        bool av = nv.available(v);
        if (av != c.available(v)) {
            assert(false);
        }

        if (av) {
            c.use(v);
            nv.use(v);
        } else {
            remain.erase(remain.begin() + pos);
        }
    }

    c.end_tree();
};


int n;

void solve() {
    vector<int> par(n, -1);
    vector<ll> f(n);

    vector<vi> adj(n);
    rng(i, 1, n) {
        int &b = par[i];
        cin >> b;
        b--;

        adj[i].push_back(b);
        adj[b].push_back(i);
    }

    foa(x, f) cin >> x;

    using pr = pair<ll, int>;
    auto cmp = [&](pr a, pr b) {
        return a.first == b.first ? a.second < b.second : a.first > b.first;
    };

    priority_queue<pair<ll, int>, vector<pair<ll, int>>, decltype(cmp)> q(cmp);
    rep(i, n) {
        q.emplace(f[i], i);
    }

    chker ck(par);
    ll ans = 0;

    debug(par);
    debug(f);
    debug(adj);

    rep(inner, n) {
        ll val;
        int person;
        tie(val, person) = q.top();
        q.pop();

        if (!ck.available(person)) {
            inner--;
            continue;
        }


        ck.use(person);
        ans += val;
        q.emplace(val + f[person] * 2, person);
    }

    cout << ans << endl;
    ck.end_tree();
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

#ifdef LOCAL
    //    rep(i, 0000) {
    //        test_checker();
    //        debug("ok");
    //    }
#endif
    while (cin >> n) {
        solve();
    }
}
accuracy: 1
time_ms: 3310
memory_kb: 231324
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define ov4(a, b, c, d, name, ...) name
#define rep3(i, a, b, c) for(ll i = (a); i < (b); i+= (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0) (__VA_ARGS__)
#define per(i, a, b) for(ll i = (a)-1; i >= (b); i--)
#define fore(e, v) for(auto&& e : v)
#define all(a) begin(a), end(a)
#define si(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template<typename T, typename S> bool chmin(T& a, const S& b) { return a > b ? a = b, 1 : 0; }
template<typename T, typename S> bool chmax(T& a, const S& b) { return a < b ? a = b, 1 : 0; }

const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;

#define i128 __int128_t

struct _ {
    _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;


using S = priority_queue<ll>;
ll sum_S(S pq) {
    ll ret = 0;
    while (pq.size() > 0) {
        ret += pq.top();
        pq.pop();
    }
    return ret;
}
void print_S(S pq) {
    while (pq.size() > 0) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << "\n";
}

int main() {
    ll N;
    cin >> N;
    vl par(N);
    vector<vl> G(N);
    rep (i, 1, N) {
        cin >> par[i];
        par[i]--;
        G[par[i]].eb(i);
    }
    vl f(N);
    rep (i, N) cin >> f[i];

    vl bfs;
    vector<bool> used(N);
    queue<ll> q({0});
    while (q.size() > 0) {
        ll now = q.front();
        q.pop();
        if (used[now]) continue;
        used[now] = true;
        bfs.eb(now);
        for (auto & to : G[now]) {
            q.push(to);
        }
    }
    vector<S> dp(N);
    vl bfs_rev = bfs;
    reverse(all(bfs_rev));
    for (auto& now : bfs_rev) {
        for (auto& to : G[now]) {
            if (dp[to].size() > dp[now].size())
                swap(dp[now], dp[to]);
            while (dp[to].size() > 0) {
                dp[now].push(dp[to].top());
                dp[to].pop();
            }
        }
        dp[now].push(f[now]);
        for (ll m = 2; true; m++) {
            ll cur = (2 * m - 1) * f[now];
            if (dp[now].top() <= cur) break;
            dp[now].pop();
            dp[now].push(cur);
        }

        // cout << "now: " << now << ", ";
        // print_S(dp[now]);
    }
    ll ans = sum_S(dp[0]);
    cout << ans << "\n";
}
accuracy: 1
time_ms: 570
memory_kb: 145140
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct HLD{
    using P=pair<int,int>;
    vector<vector<int>> g; vector<int> sz,in,out,rev,hs,par,dist;
    void dfs(int v,int p){
        par[v]=p; sz[v]=1;
        if(p!=-1)dist[v]=dist[p]+1;
        if(!g[v].empty() and g[v][0]==p)swap(g[v][0],g[v].back());
        for(auto& to:g[v])if(to!=p){
           dfs(to,v); sz[v]+=sz[to];
           if(sz[g[v][0]]<sz[to])swap(g[v][0],to);
        }
    }
    void dfs2(int v,int p,int& k){
        in[v]=k++; rev[in[v]]=v;
        for(auto& to:g[v])if(to!=p){
            hs[to]=(g[v][0]==to?hs[v]:to);
            dfs2(to,v,k);
        }
        out[v]=k;
    }
    HLD(int _n):g(_n),sz(_n),in(_n),out(_n),rev(_n),hs(_n),par(_n),dist(_n){}
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
    }
    void run(int rt=0){dfs(rt,-1); hs[rt]=rt; int k=0; dfs2(rt,-1,k);}
    int lca(int u,int v){
        for(;;v=par[hs[v]]){
            if(in[u]>in[v])swap(u,v);
            if(hs[u]==hs[v])return u;
        }
    }
    vector<P> get(int u,int p,bool es=0){
        assert(in[p]<=in[u] and out[u]<=out[p]);
        vector<P> res;
        while(hs[u]!=hs[p]){
            res.push_back({in[hs[u]],in[u]+1});
            u=par[hs[u]];
        }
        res.push_back({in[p]+es,in[u]+1});
        return res;
    }
    int jump(int u,int v,int k){
        if(k<0)return -1;
        int g=lca(u,v);
        int d0=dist[u]+dist[v]-dist[g]*2;
        if(d0<k)return -1;
        int st=u;
        if(dist[u]-dist[g]<k)st=v,k=d0-k;
        for(;;){
            int to=hs[st];
            if(in[st]-k>=in[to])return rev[in[st]-k];
            k-=in[st]-in[to]+1; st=par[to];
        }
    }
};

/**
 * @brief Heavy Light Decomposition
 */

template <typename M, typename N, M (*f)(M, M), M (*g)(M, N), N (*h)(N, N),
          M (*m1)(), N (*n1)()>
class LazySegmentTree {
    int n, sz, height;
    vector<M> data;
    vector<N> lazy;
    void update(int k) {
        data[k] = f(data[k * 2], data[k * 2 + 1]);
    }
    void apply(int k, N x) {
        data[k] = g(data[k], x);
        if (k < sz)
            lazy[k] = h(lazy[k], x);
    }
    void down(int k) {
        apply(k * 2, lazy[k]);
        apply(k * 2 + 1, lazy[k]);
        lazy[k] = n1();
    }

  public:
    LazySegmentTree(int n = 0) : LazySegmentTree(vector<M>(n, m1())) {}
    LazySegmentTree(const vector<M> &a) : n(SZ(a)) {
        sz = 1, height = 0;
        while (sz < (int)a.size())
            sz <<= 1, height++;
        data.assign(2 * sz, m1());
        lazy.assign(sz, n1());
        rep(i, 0, a.size()) data[sz + i] = a[i];
        for (int i = sz - 1; i; i--)
            update(i);
    }
    M operator[](int k) const {
        k += sz;
        rrep(i, 1, height + 1) down(k >> i);
        return data[k];
    }
    vector<M> get() {
        rep(k, 1, sz) down(k);
        return {data.begin() + sz, data.begin() + sz + n};
    }
    void set(int k, M x) {
        k += sz;
        for (int i = height; i; i--)
            down(k >> i);
        data[k] = x;
        for (int i = 1; i <= height; i++)
            update(k >> i);
    }
    void update(int L, int R, N x) {
        if (L >= R)
            return;
        L += sz, R += sz;
        for (int i = height; i; i--) {
            if (((L >> i) << i) != L)
                down(L >> i);
            if (((R >> i) << i) != R)
                down((R - 1) >> i);
        }
        int lb = L, rb = R;
        while (L < R) {
            if (L & 1)
                apply(L++, x);
            if (R & 1)
                apply(--R, x);
            L >>= 1;
            R >>= 1;
        }
        L = lb, R = rb;
        for (int i = 1; i <= height; i++) {
            if (((L >> i) << i) != L)
                update(L >> i);
            if (((R >> i) << i) != R)
                update((R - 1) >> i);
        }
    }
    M query(int L, int R) {
        if (L >= R)
            return m1();
        L += sz, R += sz;
        for (int i = height; i; i--) {
            if (((L >> i) << i) != L)
                down(L >> i);
            if (((R >> i) << i) != R)
                down((R - 1) >> i);
        }
        M lb = m1(), rb = m1();
        while (L < R) {
            if (L & 1)
                lb = f(lb, data[L++]);
            if (R & 1)
                rb = f(data[--R], rb);
            L >>= 1;
            R >>= 1;
        }
        return f(lb, rb);
    }
    template <class F> int max_right(int L, F ch) {
        if (L == n)
            return n;
        L += sz;
        rrep(i, 1, height + 1) down(L >> i);
        M sum = m1();
        do {
            while (L % 2 == 0)
                L >>= 1;
            if (!ch(f(sum, data[L]))) {
                while (L < sz) {
                    down(L);
                    L <<= 1;
                    if (ch(f(sum, data[L])))
                        sum = f(sum, data[L++]);
                }
                return L - sz;
            }
            sum = f(sum, data[L++]);
        } while ((L & -L) != L);
        return n;
    }
    template <class F> int min_left(int R, F ch) {
        if (R == 0)
            return 0;
        R += sz;
        rrep(i, 1, height + 1) down((R - 1) >> i);
        M sum = m1();
        do {
            R--;
            while (R > 1 and (R & 1))
                R >>= 1;
            if (!ch(f(data[R], sum))) {
                while (R < sz) {
                    down(R);
                    R = (R * 2 + 1);
                    if (ch(f(data[R], sum))) {
                        sum = f(data[R--], sum);
                    }
                }
                return R + 1 - sz;
            }
            sum = f(data[R], sum);
        } while ((R & -R) != R);
        return 0;
    }
};

/**
 * @brief Lazy Segment Tree
 */

ll f(ll A, ll B) {return min(A,B);}
ll g(ll A, ll B) {return A+B;}
ll h(ll A, ll B) {return A+B;}
ll e1() {return INF;}
ll e2() {return 0;}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N;
    cin >> N;
    vector<int> B(N);
    B[0] = -1;
    HLD G(N);
    rep(i,1,N) {
        cin >> B[i];
        B[i]--;
        G.add_edge(B[i],i);
    }
    G.run();
    vector<int> DP(N,1);
    rrep(i,1,N) {
        DP[B[i]] += DP[i];
    }
    vector<ll> v(N);
    rep(i,0,N) v[G.in[i]] = DP[i];
    LazySegmentTree<ll,ll,f,g,h,e1,e2> Seg(v);
    vector<ll> F(N);
    rep(i,0,N) cin >> F[i];
    vector<ll> C(N,0);
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> PQ;
    rep(i,0,N) PQ.push({F[i],i});
    auto Check = [&](int V) -> bool {
        auto ps = G.get(V,0);
        for (auto E : ps) if (Seg.query(E.first,E.second) <= 0) return false;
        return true;
    };
    rep(i,0,N) {
        while(1) {
            auto [D,P] = PQ.top();
            PQ.pop();
            if (!Check(P)) continue;
            auto ps = G.get(P,0);
            for (auto E : ps) Seg.update(E.first, E.second, -1);
            C[P]++;
            PQ.push({F[P]*(C[P]*2+1),P});
            break;
        }
    }
    ll ANS = 0;
    rep(i,0,N) ANS += F[i] * C[i] * C[i];
    cout << ANS << '\n';
}
accuracy: 1
time_ms: 1910
memory_kb: 119180
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep2(i, m, n) for (auto i = (m); i < (n); i++)
#define rep(i, n) rep2(i, 0, n)
#define repr2(i, m, n) for (auto i = (n); i-- > (m);)
#define repr(i, n) repr2(i, 0, n)
#define all(x) begin(x), end(x)
using ll = long long;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<ll>;
using vc = vector<char>;
using pii = pair<int, int>;

#ifdef LOCAL
constexpr int MaxN = 8;
#else
constexpr int MaxN = 1 << 19;
#endif


int val[MaxN*2], laz[MaxN*2];

void add(int l, int r, int x, int i = 1, int L = 0, int R = MaxN) {
  if (R <= l || r <= L) return;
  if (l <= L && R <= r) {
    laz[i] += x;
    return;
  }
  if (laz[i]) {
    val[i] += laz[i];
    laz[i*2] += laz[i];
    laz[i*2+1] += laz[i];
    laz[i] = 0;
  }
  int M = (L + R) / 2;
  add(l, r, x, i*2, L, M);
  add(l, r, x, i*2+1, M, R);
  val[i] = min(val[i*2] + laz[i*2], val[i*2+1] + laz[i*2+1]);
}

int ask(int l, int r, int i = 1, int L = 0, int R = MaxN) {
  if (R <= l || r <= L) return INT_MAX;
  if (l <= L && R <= r) {
    return val[i] + laz[i];
  }
  if (laz[i]) {
    val[i] += laz[i];
    laz[i*2] += laz[i];
    laz[i*2+1] += laz[i];
    laz[i] = 0;
  }
  int M = (L + R) / 2;
  int ansL = ask(l, r, i*2, L, M);
  int ansR = ask(l, r, i*2+1, M, R);
  return min(ansL, ansR);
}

// int main() {
//   int n, q;
//   scanf("%d%d", &n, &q);
//   while (q--) {
//     int cmd; scanf("%d", &cmd);
//     if (cmd == 0) {
//       int s, t, x; scanf("%d%d%d", &s, &t, &x);
//       t++;
//       add(s, t, x);
//     } else {
//       int s, t; scanf("%d%d", &s, &t);
//       t++;
//       printf("%d\n", ask(s, t));
//     }
//   }
// }

template <bool VALS_EDGES> struct HLD {
	int N, tim = 0;
	vector<vi> adj;
	vi par, siz, rt, pos;
	HLD(vector<vi> adj_)
		: N(size(adj_)), adj(adj_), par(N, -1), siz(N, 1),
		  rt(N),pos(N){ dfsSz(0); dfsHld(0); }
	void dfsSz(int v) {
		if (par[v] != -1) adj[v].erase(find(all(adj[v]), par[v]));
		for (int& u : adj[v]) {
			par[u] = v;
			dfsSz(u);
			siz[v] += siz[u];
			if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
		}
	}
	void dfsHld(int v) {
		pos[v] = tim++;
		for (int u : adj[v]) {
			rt[u] = (u == adj[v][0] ? rt[v] : u);
			dfsHld(u);
		}
	}
	template <class B> void process(int u, int v, B op) {
		for (; rt[u] != rt[v]; v = par[rt[v]]) {
			if (pos[rt[u]] > pos[rt[v]]) swap(u, v);
			op(pos[rt[v]], pos[v] + 1);
		}
		if (pos[u] > pos[v]) swap(u, v);
		op(pos[u] + VALS_EDGES, pos[v] + 1);
	}
	void modifyPath(int u, int v, int val) {
		process(u, v, [&](int l, int r) { add(l, r, val); });
	}
	int queryPath(int u, int v) { // Modify depending on problem
		int res = 1e9;
		process(u, v, [&](int l, int r) {
				res = min(res, ask(l, r));
		});
		return res;
	}
	int querySubtree(int v) { // modifySubtree is similar
		return ask(pos[v] + VALS_EDGES, pos[v] + siz[v]);
	}
};

void solve() {
  int n;
  scanf("%d", &n);

  // (f * (2m+1), i)
  priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> hp;

  vi par(n), m(n);
  vvi ch(n);
  vll f(n);

  par[0] = -1;
  rep(i, n-1) scanf("%d", &par[i+1]), par[i+1]--;
  rep(i, n) scanf("%lld", &f[i]);

  vvi G(n);
  rep2(v, 1, n) ch[par[v]].push_back(v);
  rep2(v, 1, n) G[par[v]].push_back(v), G[v].push_back(par[v]);
  rep(v, n) hp.emplace(f[v], v);

  HLD<false> hld(move(G));
  rep(v, n) val[hld.pos[v]+MaxN] = hld.siz[v];
  repr2(i, 1, MaxN) val[i] = min(val[i*2], val[i*2+1]);

  rep(t, n) {
    while (hld.queryPath(0, hp.top().second) == 0) hp.pop();
    int v = hp.top().second;
    hp.pop();
    m[v]++;
    hp.emplace(f[v] * (m[v]*2+1), v);
    hld.modifyPath(0, v, -1);
  }
  while (!hp.empty() && hld.queryPath(0, hp.top().second) != 0) hp.pop();
  // assert(hp.empty());
  ll ans = 0;
  rep(v, n) ans += f[v] * m[v] * m[v];
  printf("%lld\n", ans);
}

int main() {
  cin.tie(0)->sync_with_stdio(0);
  int n = 1;
  // scanf("%d", &n);
  while (n--) solve();
}
accuracy: 1
time_ms: 2170
memory_kb: 147432
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep2(i, m, n) for (auto i = (m); i < (n); i++)
#define rep(i, n) rep2(i, 0, n)
#define repr2(i, m, n) for (auto i = (n); i-- > (m);)
#define repr(i, n) repr2(i, 0, n)
#define all(x) begin(x), end(x)
using ll = long long;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<ll>;
using vc = vector<char>;
using pii = pair<int, int>;

#ifdef LOCAL
constexpr int MaxN = 4;
#else
constexpr int MaxN = 1 << 19;
#endif

int val[MaxN*2], laz[MaxN*2];

const int inf = -1e9;
struct Node {
	Node *l = 0, *r = 0;
	int lo, hi, mset = inf, madd = 0, val = -inf;
	Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of -inf
	Node(vi& v, int lo, int hi) : lo(lo), hi(hi) {
		if (lo + 1 < hi) {
			int mid = lo + (hi - lo)/2;
			l = new Node(v, lo, mid); r = new Node(v, mid, hi);
			val = min(l->val, r->val);
		}
		else val = v[lo];
	}
	int query(int L, int R) {
		if (R <= lo || hi <= L) return -inf;
		if (L <= lo && hi <= R) return val;
		push();
		return min(l->query(L, R), r->query(L, R));
	}
	void set(int L, int R, int x) {
		if (R <= lo || hi <= L) return;
		if (L <= lo && hi <= R) mset = val = x, madd = 0;
		else {
			push(), l->set(L, R, x), r->set(L, R, x);
			val = min(l->val, r->val);
		}
	}
	void add(int L, int R, int x) {
		if (R <= lo || hi <= L) return;
		if (L <= lo && hi <= R) {
			if (mset != inf) mset += x;
			else madd += x;
			val += x;
		}
		else {
			push(), l->add(L, R, x), r->add(L, R, x);
			val = min(l->val, r->val);
		}
	}
	void push() {
		if (!l) {
			int mid = lo + (hi - lo)/2;
			l = new Node(lo, mid); r = new Node(mid, hi);
		}
		if (mset != inf)
			l->set(lo,hi,mset), r->set(lo,hi,mset), mset = inf;
		else if (madd)
			l->add(lo,hi,madd), r->add(lo,hi,madd), madd = 0;
	}
};

template <bool VALS_EDGES> struct HLD {
	int N, tim = 0;
	vector<vi> adj;
	vi par, siz, rt, pos;
	Node *tree;
	HLD(vector<vi> adj_)
		: N(size(adj_)), adj(adj_), par(N, -1), siz(N, 1),
		  rt(N),pos(N),tree(new Node(0, N)){ dfsSz(0); dfsHld(0); }
	void dfsSz(int v) {
		if (par[v] != -1) adj[v].erase(find(all(adj[v]), par[v]));
		for (int& u : adj[v]) {
			par[u] = v;
			dfsSz(u);
			siz[v] += siz[u];
			if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
		}
	}
	void dfsHld(int v) {
		pos[v] = tim++;
		for (int u : adj[v]) {
			rt[u] = (u == adj[v][0] ? rt[v] : u);
			dfsHld(u);
		}
	}
	template <class B> void process(int u, int v, B op) {
		for (; rt[u] != rt[v]; v = par[rt[v]]) {
			if (pos[rt[u]] > pos[rt[v]]) swap(u, v);
			op(pos[rt[v]], pos[v] + 1);
		}
		if (pos[u] > pos[v]) swap(u, v);
		op(pos[u] + VALS_EDGES, pos[v] + 1);
	}
	void modifyPath(int u, int v, int val) {
		process(u, v, [&](int l, int r) { tree->add(l, r, val); });
	}
	int queryPath(int u, int v) { // Modify depending on problem
		int res = 1e9;
		process(u, v, [&](int l, int r) {
				res = min(res, tree->query(l, r));
		});
		return res;
	}
	int querySubtree(int v) { // modifySubtree is similar
		return tree->query(pos[v] + VALS_EDGES, pos[v] + siz[v]);
	}
};

void solve() {
  int n;
  scanf("%d", &n);

  // (f * (2m+1), i)
  priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> hp;

  vi par(n), m(n);
  vvi ch(n);
  vll f(n);

  par[0] = -1;
  rep(i, n-1) scanf("%d", &par[i+1]), par[i+1]--;
  rep(i, n) scanf("%lld", &f[i]);

  vvi G(n);
  rep2(v, 1, n) ch[par[v]].push_back(v);
  rep2(v, 1, n) G[par[v]].push_back(v), G[v].push_back(par[v]);
  rep(v, n) hp.emplace(f[v], v);

  HLD<false> hld(move(G));
  rep(v, n) hld.tree->set(hld.pos[v], hld.pos[v]+1, hld.siz[v]);

  rep(t, n) {
    while (hld.queryPath(0, hp.top().second) == 0) hp.pop();
    int v = hp.top().second;
    hp.pop();
    m[v]++;
    hp.emplace(f[v] * (m[v]*2+1), v);
    hld.modifyPath(0, v, -1);
  }
  while (!hp.empty() && hld.queryPath(0, hp.top().second) != 0) hp.pop();
  // assert(hp.empty());
  ll ans = 0;
  rep(v, n) ans += f[v] * m[v] * m[v];
  printf("%lld\n", ans);
}

int main() {
  cin.tie(0)->sync_with_stdio(0);
  int n = 1;
  // scanf("%d", &n);
  while (n--) solve();
}
accuracy: 1
time_ms: 3470
memory_kb: 167024
final_rank: 19

code_snippet: #include <bits/stdc++.h>

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <typename T> bool chmin(T &a, const T &b) {
    if (a <= b) return false;
    a = b;
    return true;
}
template <typename T> bool chmax(T &a, const T &b) {
    if (a >= b) return false;
    a = b;
    return true;
}

int main() {
    int n;
    std::cin >> n;
    std::vector<std::vector<int>> g(n); // 2次元ベクトルの初期化
    rep(i,1,n) {
        int p;
        std::cin >> p;
        p--;
        g[p].emplace_back(i);
    }
    std::vector<ll> f(n);
    rep(i,0,n) {
        std::cin >> f[i];
    }
    std::vector<ll> dp(n, 0);
    std::vector<std::priority_queue<ll>> que(n);
    
    // 合併操作を行う関数
    auto merge = [&](int u, int v) -> void {
        dp[u] += dp[v];
        if(que[u].size() < que[v].size()) {
            std::swap(que[u], que[v]);
        }
        while(!que[v].empty()) {
            ll ret = que[v].top();
            que[v].pop();
            que[u].push(ret);
        }
    };
    
    std::vector<int> sz(n, 1);
    
    // 深さ優先探索 (DFS) 関数
    std::function<void(int)> dfs = [&](int v) {
        for(auto nv: g[v]) {
            dfs(nv);
            sz[v] += sz[nv];
            merge(v, nv);
        }
        que[v].push(f[v]);
        dp[v] += f[v];
        ll now = 3 * f[v];
        rep(i,1,sz[v]) {
            if(now < que[v].top()) {
                dp[v] -= que[v].top();
                dp[v] += now;
                que[v].pop();
                que[v].push(now);
                now += 2 * f[v];
            }
            else break;
        }
    };
    
    dfs(0); // 0をルートとしてDFSを開始
    std::cout << dp[0] << '\n';
    return 0;
}
accuracy: 1
time_ms: 730
memory_kb: 115776
final_rank: 1

code_snippet: #include<bits/stdc++.h>

#include <algorithm>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <iostream>
#include <vector>
namespace atcoder {

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
    lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

}  // namespace atcoder

using namespace atcoder;
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
#define rep(i,n) for(ll i=0;i<ll(n);i++)
#define all(A) A.begin(),A.end()

vll dx = { 1,0,-1,0 };
vll dy = { 0,1,0,-1 };

const ll mod = 998244353;


ll e() { return ll(1e18); };
ll op(ll a, ll b) {
    return min(a,b);
}
ll id() { return 0; };
ll comp(ll a, ll b) { return a + b; };
ll act(ll a, ll b) {
    return a + b;
};


lazy_segtree<ll,op,e,ll,act,comp,id> seg;
struct HLD {
    using T = ll;

    vector<vector<int>> G;
    vector<int> siz, depth, par, in, out, head, heavy, ch;
    bool edge = 0;
    int cur_pos = 0;


    HLD() = default;
    HLD(const vector<vector<int>>& G) :G(G), siz(G.size()), depth(G.size()), par(G.size(), -1), in(G.size()), out(G.size()), head(G.size()), heavy(G.size(), -1), ch(G.size(), 0) {
        dfs(0);
        decompose(0, 0);
    };

    // void update(int v, const T& x)const {
    //     seg.update(in[v], x.first - seg[in[v]].first);
    // };

    void update(int u, int v,ll x) {
        while (head[u] != head[v]) {
            if (in[head[u]] > in[head[v]])swap(u, v);
            seg.apply(in[head[v]], in[v] + 1,x);
            v = par[head[v]];
        }
        if (in[u] > in[v])swap(u, v);
        seg.apply(in[u], in[v] + 1,x);
    }


    ll path_fold(int u, int v) {
        ll res = 1e18;
        while (head[u] != head[v]) {
            if (in[head[u]] > in[head[v]]) {
                swap(u, v);
            }
            ll val = seg.prod(in[head[v]], in[v] + 1);
            res = min(res,val);
            v = par[head[v]];
        }
        if (in[u] > in[v]) {
            swap(u, v);
        }
        ll val = seg.prod(in[u], in[v] + 1);
        res = min(res,val);
        return res;
    }


    // T get(int u) {
    //     return seg[in[u]];
    // }

    void dfs(int v) {
        siz[v] = 1;
        int max_siz = 0;
        for (int c : G[v]) {
            if (c == par[v])continue;
            par[c] = v;
            depth[c] = depth[v] + 1;
            dfs(c);
            siz[v] += siz[c];
            if (siz[c] > max_siz) {
                max_siz = siz[c];
                heavy[v] = c;
            }
        }
    }
    void decompose(int v, int h) {
        head[v] = h;
        in[v] = cur_pos++;
        if (heavy[v] != -1)decompose(heavy[v], h);
        for (int c : G[v]) {
            if (c != par[v] && c != heavy[v])decompose(c, c);
        }
        out[v] = cur_pos;
    }


};

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int N;
    cin >> N;
    vector<vector<int>> G(N);
    rep(i, N - 1) {
        int b;
        cin >> b;
        b--;
        G[b].push_back(i + 1);
        G[i + 1].push_back(b);
    }
    vector<ll> f(N);
    rep(i, N)cin >> f[i];

    HLD H(G);

    vll U(N);
    rep(i, N) {
        U[H.in[i]] = H.siz[i];
    }
    
    seg = lazy_segtree<ll,op,e,ll,act,comp,id>(U);

    priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> Q;

    vll tim(N, 0);
    rep(i, N) {
        Q.push({ f[i],i });
    }
    ll an = 0;
    ll ZN = N;
    while (ZN > 0) {

        ll cost = Q.top().first;
        ll n = Q.top().second;
        // cout<<cost<<" "<<n<<endl;
        ll sz = H.path_fold(n, 0);
        // rep(i, N)cout << H.get(i)<< " \n"[i == N - 1];
        Q.pop();
        if (sz > 0) {
            // cout << n << " " << cost << endl;
            an += cost;
            tim[n]++;
            cost = f[n] * (tim[n] * 2 + 1);
            Q.push({ cost,n });
            H.update(n, 0,-1);
            ll d=H.path_fold(n, 0);
            // auto p = seg.fold(H.in[0], H.in[0]+1);
            // if (ZN == 7)rep(i, N)cout << H.get(i).first << " \n"[i == N - 1];
            ZN--;
        }
        else{
            // H.update(n,0,-ll(1e7));
        }
    }
    cout << an << endl;
}
accuracy: 1
time_ms: 2670
memory_kb: 145336
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=300005,INF=15<<26;

// BIT セグ木 遅延セグ木 のみ

// from: https://gist.github.com/yosupo06/ddd51afb727600fd95d9d8ad6c3c80c9
// (based on AtCoder STL)

#include <algorithm>
#include <array>
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace atcoder {
    namespace internal {
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
        int bsf(unsigned int n) {
#ifdef _MSC_VER
            unsigned long index;
            _BitScanForward(&index, n);
            return index;
#else
            return __builtin_ctz(n);
#endif
        }
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {
    
    namespace internal {
        
#ifndef _MSC_VER
        template <class T>
        using is_signed_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value ||
        std::is_same<T, __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int128 =
        typename std::conditional<std::is_same<T, __uint128_t>::value ||
        std::is_same<T, unsigned __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using make_unsigned_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value,
        __uint128_t,
        unsigned __int128>;
        
        template <class T>
        using is_integral = typename std::conditional<std::is_integral<T>::value ||
        is_signed_int128<T>::value ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                         std::is_signed<T>::value) ||
        is_signed_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<(is_integral<T>::value &&
                                   std::is_unsigned<T>::value) ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<
        is_signed_int128<T>::value,
        make_unsigned_int128<T>,
        typename std::conditional<std::is_signed<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type>::type;
        
#else
        
        template <class T> using is_integral = typename std::is_integral<T>;
        
        template <class T>
        using is_signed_int =
        typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<is_integral<T>::value &&
        std::is_unsigned<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<is_signed_int<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type;
        
#endif
        
        template <class T>
        using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
        
        template <class T>
        using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
        
        template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
        
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <vector>

namespace atcoder {
    
    template <class T> struct fenwick_tree {
        using U = internal::to_unsigned_t<T>;
        
    public:
        fenwick_tree() : _n(0) {}
        fenwick_tree(int n) : _n(n), data(n) {}
        
        void add(int p, T x) {
            assert(0 <= p && p < _n);
            p++;
            while (p <= _n) {
                data[p - 1] += U(x);
                p += p & -p;
            }
        }
        
        T sum(int l, int r) {
            assert(0 <= l && l <= r && r <= _n);
            return sum(r) - sum(l);
        }
        
    private:
        int _n;
        std::vector<U> data;
        
        U sum(int r) {
            U s = 0;
            while (r > 0) {
                s += data[r - 1];
                r -= r & -r;
            }
            return s;
        }
    };
    
}  // namespace atcoder


#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
namespace atcoder {
    
    template <class S,
    S (*op)(S, S),
    S (*e)(),
    class F,
    S (*mapping)(F, S),
    F (*composition)(F, F),
    F (*id)()>
    struct lazy_segtree {
    public:
        lazy_segtree() : lazy_segtree(0) {}
        lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
        lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
            log = internal::ceil_pow2(_n);
            size = 1 << log;
            d = std::vector<S>(2 * size, e());
            lz = std::vector<F>(size, id());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }
        
        void set(int p, S x) {
            assert(0 <= p && p < _n);
            p += size;
            for (int i = log; i >= 1; i--) push(p >> i);
            d[p] = x;
            for (int i = 1; i <= log; i++) update(p >> i);
        }
        
        S get(int p) {
            assert(0 <= p && p < _n);
            p += size;
            for (int i = log; i >= 1; i--) push(p >> i);
            return d[p];
        }
        
        S prod(int l, int r) {
            assert(0 <= l && l <= r && r <= _n);
            if (l == r) return e();
            
            l += size;
            r += size;
            
            for (int i = log; i >= 1; i--) {
                if (((l >> i) << i) != l) push(l >> i);
                if (((r >> i) << i) != r) push(r >> i);
            }
            
            S sml = e(), smr = e();
            while (l < r) {
                if (l & 1) sml = op(sml, d[l++]);
                if (r & 1) smr = op(d[--r], smr);
                l >>= 1;
                r >>= 1;
            }
            
            return op(sml, smr);
        }
        
        S all_prod() { return d[1]; }
        
        void apply(int p, F f) {
            assert(0 <= p && p < _n);
            p += size;
            for (int i = log; i >= 1; i--) push(p >> i);
            d[p] = mapping(f, d[p]);
            for (int i = 1; i <= log; i++) update(p >> i);
        }
        void apply(int l, int r, F f) {
            assert(0 <= l && l <= r && r <= _n);
            if (l == r) return;
            
            l += size;
            r += size;
            
            for (int i = log; i >= 1; i--) {
                if (((l >> i) << i) != l) push(l >> i);
                if (((r >> i) << i) != r) push((r - 1) >> i);
            }
            
            {
                int l2 = l, r2 = r;
                while (l < r) {
                    if (l & 1) all_apply(l++, f);
                    if (r & 1) all_apply(--r, f);
                    l >>= 1;
                    r >>= 1;
                }
                l = l2;
                r = r2;
            }
            
            for (int i = 1; i <= log; i++) {
                if (((l >> i) << i) != l) update(l >> i);
                if (((r >> i) << i) != r) update((r - 1) >> i);
            }
        }
        
        template <bool (*g)(S)> int max_right(int l) {
            return max_right(l, [](S x) { return g(x); });
        }
        template <class G> int max_right(int l, G g) {
            assert(0 <= l && l <= _n);
            assert(g(e()));
            if (l == _n) return _n;
            l += size;
            for (int i = log; i >= 1; i--) push(l >> i);
            S sm = e();
            do {
                while (l % 2 == 0) l >>= 1;
                if (!g(op(sm, d[l]))) {
                    while (l < size) {
                        push(l);
                        l = (2 * l);
                        if (g(op(sm, d[l]))) {
                            sm = op(sm, d[l]);
                            l++;
                        }
                    }
                    return l - size;
                }
                sm = op(sm, d[l]);
                l++;
            } while ((l & -l) != l);
            return _n;
        }
        
        template <bool (*g)(S)> int min_left(int r) {
            return min_left(r, [](S x) { return g(x); });
        }
        template <class G> int min_left(int r, G g) {
            assert(0 <= r && r <= _n);
            assert(g(e()));
            if (r == 0) return 0;
            r += size;
            for (int i = log; i >= 1; i--) push((r - 1) >> i);
            S sm = e();
            do {
                r--;
                while (r > 1 && (r % 2)) r >>= 1;
                if (!g(op(d[r], sm))) {
                    while (r < size) {
                        push(r);
                        r = (2 * r + 1);
                        if (g(op(d[r], sm))) {
                            sm = op(d[r], sm);
                            r--;
                        }
                    }
                    return r + 1 - size;
                }
                sm = op(d[r], sm);
            } while ((r & -r) != r);
            return 0;
        }
        
    private:
        int _n, size, log;
        std::vector<S> d;
        std::vector<F> lz;
        
        void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
        void all_apply(int k, F f) {
            d[k] = mapping(f, d[k]);
            if (k < size) lz[k] = composition(f, lz[k]);
        }
        void push(int k) {
            all_apply(2 * k, lz[k]);
            all_apply(2 * k + 1, lz[k]);
            lz[k] = id();
        }
    };
    
}  // namespace atcoder

#include <algorithm>
#include <cassert>
#include <vector>

namespace atcoder {
    
    template <class S, S (*op)(S, S), S (*e)()> struct segtree {
    public:
        segtree() : segtree(0) {}
        segtree(int n) : segtree(std::vector<S>(n, e())) {}
        segtree(const std::vector<S>& v) : _n(int(v.size())) {
            log = internal::ceil_pow2(_n);
            size = 1 << log;
            d = std::vector<S>(2 * size, e());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }
        
        void set(int p, S x) {
            assert(0 <= p && p < _n);
            p += size;
            d[p] = x;
            for (int i = 1; i <= log; i++) update(p >> i);
        }
        
        S get(int p) {
            assert(0 <= p && p < _n);
            return d[p + size];
        }
        
        S prod(int l, int r) {
            assert(0 <= l && l <= r && r <= _n);
            S sml = e(), smr = e();
            l += size;
            r += size;
            
            while (l < r) {
                if (l & 1) sml = op(sml, d[l++]);
                if (r & 1) smr = op(d[--r], smr);
                l >>= 1;
                r >>= 1;
            }
            return op(sml, smr);
        }
        
        S all_prod() { return d[1]; }
        
        template <bool (*f)(S)> int max_right(int l) {
            return max_right(l, [](S x) { return f(x); });
        }
        template <class F> int max_right(int l, F f) {
            assert(0 <= l && l <= _n);
            assert(f(e()));
            if (l == _n) return _n;
            l += size;
            S sm = e();
            do {
                while (l % 2 == 0) l >>= 1;
                if (!f(op(sm, d[l]))) {
                    while (l < size) {
                        l = (2 * l);
                        if (f(op(sm, d[l]))) {
                            sm = op(sm, d[l]);
                            l++;
                        }
                    }
                    return l - size;
                }
                sm = op(sm, d[l]);
                l++;
            } while ((l & -l) != l);
            return _n;
        }
        
        template <bool (*f)(S)> int min_left(int r) {
            return min_left(r, [](S x) { return f(x); });
        }
        template <class F> int min_left(int r, F f) {
            assert(0 <= r && r <= _n);
            assert(f(e()));
            if (r == 0) return 0;
            r += size;
            S sm = e();
            do {
                r--;
                while (r > 1 && (r % 2)) r >>= 1;
                if (!f(op(d[r], sm))) {
                    while (r < size) {
                        r = (2 * r + 1);
                        if (f(op(d[r], sm))) {
                            sm = op(d[r], sm);
                            r--;
                        }
                    }
                    return r + 1 - size;
                }
                sm = op(d[r], sm);
            } while ((r & -r) != r);
            return 0;
        }
        
    private:
        int _n, size, log;
        std::vector<S> d;
        
        void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    };
    
}  // namespace atcoder

struct HeavyLightDecomposition{
    int n;
    vector<int> sz,in,out,nxt,par,depth;
    vector<vector<int>> G;
    
    HeavyLightDecomposition(){}
    
    HeavyLightDecomposition(int n_){
        n=n_;
        sz.assign(n,0);
        in.assign(n,0);
        out.assign(n,0);
        nxt.assign(n,0);
        par.assign(n,0);
        depth.assign(n,0);
        G.assign(n,vector<int>());
    }
    
    void add_edge(int u,int v){
        G[u].push_back(v);
        G[v].push_back(u);
    }
    
    void dfs_sz(int u,int p){
        par[u]=p;
        sz[u]=1;
        if(G[u].size()&&G[u][0]==p) swap(G[u][0],G[u].back());
        for(auto &a:G[u]){
            if(a==p) continue;
            depth[a]=depth[u]+1;
            dfs_sz(a,u);
            sz[u]+=sz[a];
            if(sz[a]>sz[G[u][0]]){
                swap(a,G[u][0]);
            }
        }
    }
    
    void dfs_hld(int u,int p,int &t){
        in[u]=t++;
        for(auto a:G[u]){
            if(a==p) continue;
            nxt[a]=(a==G[u][0] ? nxt[u] : a);
            dfs_hld(a,u,t);
        }
        out[u]=t;
    }
    
    void build(int u){
        int t=0;
        dfs_sz(u,-1);
        dfs_hld(u,-1,t);
    }
    
    int lca(int u,int v){
        if(in[u]>in[v]) swap(u,v);
        if(nxt[u]==nxt[v]) return u;
        return lca(u,par[nxt[v]]);
    }
    
    int mov1(int a,int b){
        if(a==b) return a;
        int c=lca(a,b);
        if(c==a){
            int l=0,r=si(G[a]);
            while(r-l>1){
                int m=(l+r)/2;
                if(par[a]==G[a][m]){
                    if(m+1<r){
                        if(r-l==2){
                            l=m+1;
                            break;
                        }
                        if(in[G[a][m+1]]<=in[b]) l=m+1;
                        else r=m;
                    }else{
                        if(r-l==2){
                            l=m-1;
                            break;
                        }
                        if(in[G[a][m-1]]<=in[b]) l=m-1;
                        else r=m-1;
                    }
                }else{
                    if(in[G[a][m]]<=in[b]) l=m;
                    else r=m;
                }
            }
            if(par[a]!=G[a][l]) return G[a][l];
            else return G[a][l+1];
            //return G[a][l];
        }else{
            return par[a];
        }
    }
    //aからbに向かって1進んだところ
};
//部分木クエリはquery(in[a],out[a])
//点はquery(in[a],in[a]+1)

using T=ll;
using E=ll;

T f(T a,T b){
    return min(a,b);
}

T g(E a,T b){
    return a+b;
}

E h(E a,E b){
    return a+b;
}

T ti(){
    return INF;
}

E ei(){
    return 0;
}
//部分木クエリはquery(in[a],out[a])
//点はquery(in[a],in[a]+1)

atcoder::lazy_segtree<T,f,ti,E,g,h,ei> seg;
HeavyLightDecomposition hld;

//hld=HeavyLightDecomposition(N)、のようにmainに書く;

//buildするときは根が0じゃないとバグるらしい、適宜番号振りを頑張ってくれ

///ここまで貼る


void UPD(int l,int r,ll x){
    seg.apply(l,r,x);
}

void QUE(int l,int r,ll &x,bool type){
    chmin(x,seg.prod(l,r));
}

void updateV(int a,int b){
    int c=hld.lca(a,b);
    
    while(a!=-1){
        if(hld.nxt[a]==hld.nxt[c]){
            UPD(hld.in[c],hld.in[a]+1,-1);
            break;
        }
        UPD(hld.in[hld.nxt[a]],hld.in[a]+1,-1);
        a=hld.par[hld.nxt[a]];
    }
    while(b!=-1){
        if(hld.nxt[b]==hld.nxt[c]){
            UPD(hld.in[c],hld.in[b]+1,-1);
            break;
        }
        UPD(hld.in[hld.nxt[b]],hld.in[b]+1,-1);
        b=hld.par[hld.nxt[b]];
    }
    
    UPD(hld.in[c],hld.in[c]+1,1);
    //cを2回やってるので打ち消し
}

ll solveV(int a,int b){
    int c=hld.lca(a,b);
    ll res=1;
    
    while(a!=-1){
        if(hld.nxt[a]==hld.nxt[c]){
            QUE(hld.in[c],hld.in[a]+1,res,0);
            break;
        }
        QUE(hld.in[hld.nxt[a]],hld.in[a]+1,res,0);
        a=hld.par[hld.nxt[a]];
    }
    while(b!=-1){
        if(hld.nxt[b]==hld.nxt[c]){
            QUE(hld.in[c],hld.in[b]+1,res,0);
            break;
        }
        QUE(hld.in[hld.nxt[b]],hld.in[b]+1,res,0);
        b=hld.par[hld.nxt[b]];
    }
    
    QUE(hld.in[c],hld.in[c]+1,res,1);
    //cを2回やってるので打ち消し
    
    return res;
}

//頂点属性

// seg[in[x]]に頂点xの情報を持たせる

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    atcoder::fenwick_tree<ll> BI(N);
    hld=HeavyLightDecomposition(N);
    
    for(int i=1;i<N;i++){
        int p;cin>>p;p--;
        hld.add_edge(p,i);
    }
    hld.build(0);
    
    vector<T> def(N);
    for(int i=0;i<N;i++) def[hld.in[i]]=hld.sz[i];
    seg=atcoder::lazy_segtree<T,f,ti,E,g,h,ei>(def);
    
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> PQ;
    
    vector<ll> cn(N,1),F(N);
    for(int i=0;i<N;i++){
        cin>>F[i];
        PQ.push(mp(F[i]*cn[i],i));
    }
    
    ll ans=0,e=0;
    
    while(!PQ.empty()){
        auto [x,i]=PQ.top();PQ.pop();
        ll sum=BI.sum(hld.in[i],hld.out[i]);
        ll z=solveV(0,i);
        //cout<<x<<" "<<i<<" "<<z<<endl;
        if(sum<hld.sz[i]&&z>=1){
            e++;
            //cout<<x<<" "<<i<<endl;
            BI.add(hld.in[i],1);
            updateV(0,i);
            ans+=x;
            cn[i]+=2;
            PQ.push(mp(F[i]*cn[i],i));
        }
        if(e==N) break;
    }
    
    
    cout<<ans<<endl;
    
}
accuracy: 1
time_ms: 2840
memory_kb: 118716
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(int)a;i<(int)b;i++)
#define all(p) p.begin(),p.end()
using ll =long long;

// 注意 : mapping(id(), s) は s を返すこと
template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
struct lazy_segtree {
    int n, size = 1, lg = 0;
    vector<S> d;
    vector<F> lz;
    lazy_segtree(const vector<S>& v) : n(v.size()) {
        while(n > size) {
            lg++; size *= 2;
        }
        d.assign(2 * size, e());
        lz.assign(size, id());
        for(int i = 0; i < n; i++) d[size + i] = v[i];
        for(int i = size - 1; i >= 1; i--) update(i);
    }
    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if(k < size) {
            lz[k] = composition(f, lz[k]);
            // for Segment Tree Beats!
            // mapping のときに fail を立てると下から計算してくれる
            // if (d[k].fail) { push(k); update(k); }
        }
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
    void set(int p, S x) {
        p += size;
        for(int i = lg; i >= 1; i--) push(p >> i);
        d[p] = x;
        for(int i = 1; i <= lg; i++) update(p >> i);
    }
    S prod(int l, int r) {
        if(l == r) return e();
        l += size; r += size;
        for(int i = lg; i >= 1; i--) {
            if(l >> i << i != l) push(l >> i);
            if(r >> i << i != r) push((r - 1) >> i);
        }
        S L = e(), R = e();
        for(; l < r; l >>= 1, r >>= 1) {
            if(l & 1) L = op(L, d[l++]);
            if(r & 1) R = op(d[--r], R);
        }
        return op(L, R);
    }
    void apply(int l, int r, F f) {
        if(l == r) return;
        l += size;
        r += size;
        for(int i = lg; i >= 1; i--) {
            if(l >> i << i != l) push(l >> i);
            if(r >> i << i != r) push((r - 1) >> i);
        }
        const int l2 = l, r2 = r;
        for(; l < r; l >>= 1, r >>= 1) {
            if(l & 1) all_apply(l++, f);
            if(r & 1) all_apply(--r, f);
        }
        l = l2; r = r2;
        for(int i = 1; i <= lg; i++) {
            if(((l >> i) << i) != l) update(l >> i);
            if(((r >> i) << i) != r) update((r - 1) >> i);
        }
    }
};
template <typename G>
struct HeavyLightDecomposition {
	void dfs_sz(int cur) {
		size[cur] = 1;
		for(auto& dst : g[cur]) {
			if(dst == par[cur]) {
				if(g[cur].size() >= 2 & dst == g[cur][0]) swap(g[cur][0], g[cur][1]);
				else continue;
			}
			depth[dst] = depth[cur] + 1;
			par[dst] = cur;
			dfs_sz(dst);
			size[cur] += size[dst];
			if(size[dst] > size[g[cur][0]]) swap(dst, g[cur][0]);
		}
	}
	void dfs_hld(int cur) {
		down[cur] = id++;
		for(auto dst : g[cur]) if(dst != par[cur]) {
			nxt[dst] = dst == g[cur][0] ? nxt[cur] : dst;
			dfs_hld(dst);
		}
		up[cur] = id;
	}
	// [u, v)
	vector<pair<int, int>> ascend(int u, int v) const {
		vector<pair<int, int>> res;
		while(nxt[u] != nxt[v]) {
			res.emplace_back(down[u], down[nxt[u]]);
			u = par[nxt[u]];
		}
		if(u != v) res.emplace_back(down[u], down[v] + 1);
		return res;
	}
	// (u, v]
	vector<pair<int, int>> descend(int u, int v) const {
		if(u == v) return {};
		if(nxt[u] == nxt[v]) return {{down[u] + 1, down[v]}};
		auto res = descend(u, par[nxt[v]]);
		res.emplace_back(down[nxt[v]], down[v]);
		return res;
	}
	G& g;
	int n, id;
	vector<int> size, depth, down, up, nxt, par;
	HeavyLightDecomposition(G& _g, int root = 0) : g(_g), n(g.size()), id(0), size(n), depth(n), down(n, -1), up(n, -1), nxt(n, root), par(n, root) {
		dfs_sz(root);
		dfs_hld(root);
	}
	pair<int, int> idx(int i) const { return {down[i], up[i]}; }
	template <typename F>
	void path_query(int u, int v, bool vertex, const F& f) {
		int l = lca(u, v);
		for(auto& [a, b] : ascend(u, l)) {
			int s = a + 1, t = b;
			s > t ? f(t, s) : f(s, t);
		}
		if(vertex) f(down[l], down[l] + 1);
		for(auto& [a, b] : descend(l, v)) {
			int s = a, t = b + 1;
			s > t ? f(t, s) : f(s, t);
		}
	}
	template <typename F>
	void path_query_easy (int u, int v, bool vertex, const F& f) {
		int l = lca(u, v);
		for(auto& [a, b] : ascend(u, l)) f(a + 1, b);
		if(vertex) f(down[l], down[l] + 1);
		for(auto& [a, b] : descend(l, v)) f(a, b + 1);
	}
	template <typename F> void subtree_query(int u, bool vertex, const F& f) {
		f(down[u] + !vertex, up[u]);
	}
	int lca(int a, int b) {
		while(nxt[a] != nxt[b]) {
			if(down[a] < down[b]) swap(a, b);
			a = par[nxt[a]];
		}
		return depth[a] < depth[b] ? a : b;
	}
	int dist(int a, int b) { return depth[a] + depth[b] - depth[lca(a, b)] * 2; }
};

int op(int a,int b){
    return min(a,b);
}
int e(){
    return (1<<25);
}
int comp(int a,int b){
    return a+b;
}
int mapping(int a,int b){
    return a+b;
}
int id(){
    return 0;
}

int main(){
    int N;
    cin>>N;
    vector<vector<int>> G(N);
    rep(i,1,N){
        int b;
        cin>>b;
        b--;
        G[b].push_back(i);
        G[i].push_back(b);
    }
    vector<ll> F(N);
    vector<int> C(N,3);
    rep(i,0,N) cin>>F[i];
    ll ans=0;
    vector<int> po_seg(N,e());
    lazy_segtree<int,op,e,int,mapping,comp,id> seg(po_seg);
    HeavyLightDecomposition H(G);
    vector<int> W(N,1);
    for(int i=N-1;i>=0;i--) for(auto x:G[i]) if(i<x) W[i]+=W[x];
    rep(i,0,N) seg.set(H.idx(i).first,W[i]);
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> pq;
    rep(i,0,N) pq.push({F[i],i});
    int P_res;
    auto PROD=[&](int a,int b) -> void {
        P_res=op(P_res,seg.prod(a,b));
    };
    auto APL=[&](int a,int b) -> void {
        seg.apply(a,b,-1);
    };
    while(!pq.empty()){
        auto tmp=pq.top();
        pq.pop();
        P_res=e();
        H.path_query_easy(0,tmp.second,1,PROD);
        if(P_res==0){
            continue;
        }
        //cout<<tmp.first<<" "<<tmp.second<<endl;
        ans+=tmp.first;
        tmp.first=C[tmp.second]*F[tmp.second];
        C[tmp.second]+=2;
        pq.push(tmp);
        H.path_query_easy(0,tmp.second,1,APL);
    }
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 2660
memory_kb: 98088
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(int)a;i<(int)b;i++)
#define all(p) p.begin(),p.end()
using ll =long long;

// 注意 : mapping(id(), s) は s を返すこと
template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
struct lazy_segtree {
    int n, size = 1, lg = 0;
    vector<S> d;
    vector<F> lz;
    lazy_segtree(const vector<S>& v) : n(v.size()) {
        while(n > size) {
            lg++; size *= 2;
        }
        d.assign(2 * size, e());
        lz.assign(size, id());
        for(int i = 0; i < n; i++) d[size + i] = v[i];
        for(int i = size - 1; i >= 1; i--) update(i);
    }
    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if(k < size) {
            lz[k] = composition(f, lz[k]);
            // for Segment Tree Beats!
            // mapping のときに fail を立てると下から計算してくれる
            // if (d[k].fail) { push(k); update(k); }
        }
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
    void set(int p, S x) {
        p += size;
        for(int i = lg; i >= 1; i--) push(p >> i);
        d[p] = x;
        for(int i = 1; i <= lg; i++) update(p >> i);
    }
    S prod(int l, int r) {
        if(l == r) return e();
        l += size; r += size;
        for(int i = lg; i >= 1; i--) {
            if(l >> i << i != l) push(l >> i);
            if(r >> i << i != r) push((r - 1) >> i);
        }
        S L = e(), R = e();
        for(; l < r; l >>= 1, r >>= 1) {
            if(l & 1) L = op(L, d[l++]);
            if(r & 1) R = op(d[--r], R);
        }
        return op(L, R);
    }
    void apply(int l, int r, F f) {
        if(l == r) return;
        l += size;
        r += size;
        for(int i = lg; i >= 1; i--) {
            if(l >> i << i != l) push(l >> i);
            if(r >> i << i != r) push((r - 1) >> i);
        }
        const int l2 = l, r2 = r;
        for(; l < r; l >>= 1, r >>= 1) {
            if(l & 1) all_apply(l++, f);
            if(r & 1) all_apply(--r, f);
        }
        l = l2; r = r2;
        for(int i = 1; i <= lg; i++) {
            if(((l >> i) << i) != l) update(l >> i);
            if(((r >> i) << i) != r) update((r - 1) >> i);
        }
    }
};
template <typename G>
struct HeavyLightDecomposition {
    void dfs_sz(int cur) {
        size[cur] = 1;
        for(auto& dst : g[cur]) {
            if(dst == par[cur]) {
                if(g[cur].size() >= 2 & dst == g[cur][0]) swap(g[cur][0], g[cur][1]);
                else continue;
            }
            depth[dst] = depth[cur] + 1;
            par[dst] = cur;
            dfs_sz(dst);
            size[cur] += size[dst];
            if(size[dst] > size[g[cur][0]]) {
                swap(dst, g[cur][0]);
            }
        }
    }
    void dfs_hld(int cur) {
        down[cur] = id++;
        for(auto dst : g[cur]) {
            if(dst == par[cur]) continue;
            nxt[dst] = dst == g[cur][0] ? nxt[cur] : dst;
            dfs_hld(dst);
        }
        up[cur] = id;
    }
    // [u, v)
    vector<pair<int, int>> ascend(int u, int v) const {
        vector<pair<int, int>> res;
        while(nxt[u] != nxt[v]) {
            res.emplace_back(down[u], down[nxt[u]]);
            u = par[nxt[u]];
        }
        if(u != v) res.emplace_back(down[u], down[v] + 1);
        return res;
    }
    // (u, v]
    vector<pair<int, int>> descend(int u, int v) const {
        if(u == v) return {};
        if(nxt[u] == nxt[v]) return {{down[u] + 1, down[v]}};
        auto res = descend(u, par[nxt[v]]);
        res.emplace_back(down[nxt[v]], down[v]);
        return res;
    }
    G& g;
    int n, id;
    vector<int> size, depth, down, up, nxt, par;
    HeavyLightDecomposition(G& _g, int root = 0) : g(_g), n(g.size()), id(0), size(n), depth(n), down(n, -1), up(n, -1), nxt(n, root), par(n, root) {
        dfs_sz(root);
        dfs_hld(root);
    }
    pair<int, int> idx(int i) const { return {down[i], up[i]}; }
    template <typename F>
    void path_query(int u, int v, bool vertex, const F& f) {
        int l = lca(u, v);
        for(auto& [a, b] : ascend(u, l)) {
            int s = a + 1, t = b;
            s > t ? f(t, s) : f(s, t);
        }
        if(vertex) f(down[l], down[l] + 1);
        for(auto& [a, b] : descend(l, v)) {
            int s = a, t = b + 1;
            s > t ? f(t, s) : f(s, t);
        }
    }
    template <typename F>
    void path_noncommutative_query(int u, int v, bool vertex, const F& f) {
        int l = lca(u, v);
        for(auto& [a, b] : ascend(u, l)) f(a + 1, b);
        if(vertex) f(down[l], down[l] + 1);
        for(auto& [a, b] : descend(l, v)) f(a, b + 1);
    }
    template <typename F> void subtree_query(int u, bool vertex, const F& f) {
        f(down[u] + !vertex, up[u]);
    }
    int lca(int a, int b) {
        while(nxt[a] != nxt[b]) {
            if(down[a] < down[b]) swap(a, b);
            a = par[nxt[a]];
        }
        return depth[a] < depth[b] ? a : b;
    }
    int dist(int a, int b) { return depth[a] + depth[b] - depth[lca(a, b)] * 2; }
};

int op(int a,int b){
    return min(a,b);
}
int e(){
    return (1<<25);
}
int comp(int a,int b){
    return a+b;
}
int mapping(int a,int b){
    return a+b;
}
int id(){
    return 0;
}

int main(){
    int N;
    cin>>N;
    vector<vector<int>> G(N);
    rep(i,1,N){
        int b;
        cin>>b;
        b--;
        G[b].push_back(i);
        G[i].push_back(b);
    }
    vector<ll> F(N);
    vector<int> C(N,3);
    rep(i,0,N) cin>>F[i];
    ll ans=0;
    vector<int> po_seg(N,e());
    lazy_segtree<int,op,e,int,mapping,comp,id> seg(po_seg);
    HeavyLightDecomposition H(G);
    vector<int> W(N,1);
    for(int i=N-1;i>=0;i--) for(auto x:G[i]) if(i<x) W[i]+=W[x];
    rep(i,0,N) seg.set(H.idx(i).first,W[i]);
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> pq;
    rep(i,0,N) pq.push({F[i],i});
    int P_res;
    auto PROD=[&](int a,int b) -> void {
        P_res=op(P_res,seg.prod(a,b));
    };
    auto APL=[&](int a,int b) -> void {
        seg.apply(a,b,-1);
    };
    while(!pq.empty()){
        auto tmp=pq.top();
        pq.pop();
        P_res=e();
        H.path_noncommutative_query(0,tmp.second,1,PROD);
        if(P_res==0){
            continue;
        }
        //cout<<tmp.first<<" "<<tmp.second<<endl;
        ans+=tmp.first;
        tmp.first=C[tmp.second]*F[tmp.second];
        C[tmp.second]+=2;
        pq.push(tmp);
        H.path_noncommutative_query(0,tmp.second,1,APL);
    }
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 2670
memory_kb: 98732
final_rank: 12

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) {
        os << '-';
        y *= -1;
    }
    std::vector<int> ny;
    while(y > 0) {
        ny.push_back(y % 10);
        y /= 10;
    }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ok - ng) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 2 "A.cpp"

int main() {
    int n = in();
    vector<int> b = in(n - 1);
    vector<i64> f = in(n);

    vector<vector<int>> c(n);
    for(int i : rep(n - 1)) {
        c[b[i] - 1].push_back(i + 1);
    }

    vector<i64> dp(n, 0);
    vector<heap_max<i64>> h(n);
    
    auto merge = [&](int u, int v) {
        dp[u] += dp[v];
        if(h[u].size() < h[v].size()) swap(h[u], h[v]);
        while(not h[v].empty()) {
            i64 x = h[v].top(); h[v].pop();
            h[u].push(x);
        }
    };

    vector<int> sz(n, 1);
    for(int i : revrep(n)) {
        for(int to : c[i]) merge(i, to);
        h[i].push(f[i]);
        dp[i] += f[i];

        for(i64 k = 1; ; k++) {
            i64 v = (2 * k + 1) * f[i];
            if(v < h[i].top()) {
                dp[i] -= h[i].top();
                dp[i] += v;
                h[i].pop();
                h[i].push(v);
            } else break;
        }
    }

    print(dp[0]);
}
accuracy: 1
time_ms: 560
memory_kb: 127428
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll =long long;
using vl=vector<ll>;
using vvl=vector<vl>;
#define rep(i,a,b) for(ll i =(a); i <(b);i++)
template<class T> bool chmin(T &a,T b){
    if(a>b){
        a=b;
        return true;
    }
    return false;
}

template<class T> bool chmax(T &a,T b){
    if(a<b){
        a=b;
        return true;
    }
    return false;
}

template<class S,S (*op)(S,S),S (*e)()>
struct segtree{
    vector<S> d;
    int size=1;
    int n;
    segtree(int n_):n(n_){
        while(size<n) size*=2;
        d.resize(size*2,e());
    }
    void set(int p,S x){
        p+=size;
        d[p]=x;
        while(p>1){
            p/=2;d[p]=op(d[p*2],d[p*2+1]);
        }
    }
    S get(int p){return d[p+size];}
    S prod(int l,int r){
        l+=size,r+=size;
        S L=e(),R=e();
        while(l<r){
            if(l&1) L=op(L,d[l++]);
            if(r&1) R=op(d[--r],R);
            l/=2,r/=2;
        }
        return op(L,R);
    }
    template<class F> int max_right(int l,F f)const{
        if(l==n) return n;
        l+=size;
        S sm=e();
        do{
            while(l%2==0) l>>=1;
            if(!f(op(sm,d[l]))){
                while(l<size){
                    l=(2*l);
                    if(f(op(sm,d[l]))){
                        sm=op(sm,d[l++]);
                    }
                }
                return l-size;
            }
            sm=op(sm,d[l]);
            l++;
        }while((l&-l)!=l);
        return n;
    }
};

struct F{
    int sum;
    int val;
};
const int INF=(1<<28);

F op(F l,F r){
    if(l.sum==INF) return r;
    if(r.sum==INF) return l;
    chmin(l.val,r.val+l.sum);
    chmin(l.val,l.sum);
    l.sum+=r.sum;
    return l;
}
F e(){
    return {INF,INF};
}
bool g(F x){
    return x.val>0;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    cin>>N;
    vector<vector<int>> G(N);
    vector<int> pare(N);
    vector<ll> f(N);
    rep(i,1,N){
        int a;
        cin>>a;
        a--;
        pare[i]=a;
        G[a].push_back(i);
    }
    rep(i,0,N){
        cin>>f[i];
    }
    pare[0]=-2;
    vector<int> to(N),order,rev(N);
    segtree<F,op,e> seg(N);
    vector<int> size(N);
    for(int i=N-1;i>=0;i--){
        for(auto x:G[i]) size[i]+=size[x];
        size[i]++;
    }
    auto dfs=[&](auto self,int var,int top) -> void{
        rev[var]=order.size();
        order.push_back(var);
        to[var]=top;
        if(top==var) seg.set(rev[var],{size[var],size[var]});
        else{
            int tmp=size[var]-size[pare[var]];
            seg.set(rev[var],{tmp,tmp});
        }
        int nx=-1,val=-1;
        for(auto x:G[var]){
            if(chmax(val,size[x])){
                nx=x;
            }
        }
        if(nx==-1) return;
        self(self,nx,top);
        for(auto x:G[var]){
            if(nx!=x){
                self(self,x,x);
            }
        }
    };
    dfs(dfs,0,0);
    vector<ll> use(N);
    ll ans=0;
    priority_queue<pair<ll,int>,vector<pair<ll,int>>, greater<pair<ll,int>>> pq;
    rep(i,0,N){
        pq.push({f[i],i});
    }
    vector<int> death(N);
    vector<int> death_order;
    int death_ind=0;
    rep(i,0,N){
        pair<ll,int> tmp;
        while(true){
            tmp=pq.top();
            if(death[tmp.second]){
                pq.pop();
            }
            else break;
        }
        ans+=tmp.first;
        int ind=tmp.second;
        use[ind]++;
        pq.pop();
        pq.push({(use[ind]*2+1)*f[ind],ind});
        while(ind!=pare[0]){
            int l=rev[to[ind]];
            int r=rev[ind]+1;
            F d=seg.get(l);
            d.sum--;
            d.val=d.sum;
            seg.set(l,d);
            if(size[ind]!=1){
                d=seg.get(r);
                d.sum++;
                d.val=d.sum;
                seg.set(r,d);
            }
            int b=seg.max_right(l,g);
            if(b<r){
                death_order.push_back(order[b]);
                death[order[b]]=1;
            }        /*
            cout<<l<<" "<<r<<endl;
            rep(j,0,N){
                cout<<"("<<seg.get(j).sum<<" "<<seg.get(j).val<<") ";
            }  */
            //cout<<endl;
            ind=pare[to[ind]];
        }
        while(death_ind!=(int)death_order.size()){
            int a=death_order[death_ind];
            death_ind++;
            for(auto x:G[a]){
                if(death[x]==0){
                    death[x]=1;
                    death_order.push_back(x);
                }
            }
        }
    }
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 1100
memory_kb: 124868
final_rank: 8

code_snippet: #include <bits/stdc++.h>

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <typename T> bool chmin(T &a, const T &b) {
    if (a <= b) return false;
    a = b;
    return true;
}
template <typename T> bool chmax(T &a, const T &b) {
    if (a >= b) return false;
    a = b;
    return true;
}

int main() {
    int n;
    std::cin >> n;
    std::vector g(n, std::vector<int>());
    rep(i,1,n) {
        int p;
        std::cin >> p;
        p--;
        g[p].emplace_back(i);
    }
    std::vector<ll> f(n);
    rep(i,0,n) {
        std::cin >> f[i];
    }
    std::vector<ll> dp(n, 0);
    std::vector<std::priority_queue<ll>> que(n);
    auto merge = [&](int u, int v) -> void {
        dp[u] += dp[v];
        if(que[u].size() < que[v].size()) {
            std::swap(que[u], que[v]);
        }
        while(!que[v].empty()) {
            ll ret = que[v].top();
            que[v].pop();
            que[u].push(ret);
        }
    };
    std::vector<int> sz(n, 1);
    auto dfs = [&](auto &&self, int v) -> void {
        for(auto nv: g[v]) {
            self(self, nv);
            sz[v] += sz[nv];
            merge(v, nv);
        }
        que[v].push(f[v]);
        dp[v] += f[v];
        ll now = 3 * f[v];
        rep(i,1,sz[v]) {
            if(now < que[v].top()) {
                dp[v] -= que[v].top();
                dp[v] += now;
                que[v].pop();
                que[v].push(now);
                now += 2 * f[v];
            }
            else break;
        }
    };
    dfs(dfs, 0);
    std::cout << dp[0] << '\n';
}
accuracy: 1
time_ms: 700
memory_kb: 123068
final_rank: 3