Problem:
n
個の都市と
n − 1
本の道路があり，木になっている．都市には 1 から
n
までの番号がつけられている．都市 1 を根とみたとき，都市
i
の親は
p
i
であり，
i
と
p
i
の距離は
d
i
である．すぬけ君は，1 以上
n
以下の各
k
に対し，次の問題を解きたい．
ある都市から都市 1, . . . . ,
k
への距離の和の最小値

\begin{eqnarray}
min_{1 \leq v \leq n} \{ \sum^k_{i=1} dist(i, v)\}  \;\;\;\;\;\;\;\;\;\;\;\;\;\;(2)
\end{eqnarray}
を求めよ．ただし
dist(u, v)
は
u
と
v
の距離をあらわす．
Constraints
1 ≤
n
≤ 200000
1 ≤
p
i
≤
n
1 ≤
d
i
≤ 200000
p
i
によって表されるグラフは木になっている
入力は全て整数である
Input
n
p
2
d
2
. . .
p
n
d
n
Output
n
行出力せよ．
i
行目には，
k = i
のときの答えを出力せよ．
Sample Input 1
10
4 1
1 1
3 1
3 1
5 1
6 1
6 1
8 1
4 1
Sample Output 1
0
3
3
4
5
7
10
13
16
19
Sample Input 2
15
1 3
12 5
5 2
12 1
7 5
5 1
6 1
12 1
11 1
12 4
1 1
5 5
10 4
1 2
Sample Output 2
0
3
9
13
14
21
22
29
31
37
41
41
47
56
59

Submitted solutions:

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
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> void chmax(A& l, const B& r){ if(l < r) l = r; }
template <class A, class B> void chmin(A& l, const B& r){ if(r < l) l = r; }

template<class T> using nega_queue = priority_queue<T, V<T>, greater<T>>;

#include <utility>
#include <cassert>

namespace nachia{

template<class Elem>
class CsrArray{
public:
    struct ListRange{
        using iterator = typename std::vector<Elem>::iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        Elem& operator[](int i) const { return begi[i]; }
    };
    struct ConstListRange{
        using iterator = typename std::vector<Elem>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Elem& operator[](int i) const { return begi[i]; }
    };
private:
    int m_n;
    std::vector<Elem> m_list;
    std::vector<int> m_pos;
public:
    CsrArray() : m_n(0), m_list(), m_pos() {}
    static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
        CsrArray res;
        res.m_n = n;
        std::vector<int> buf(n+1, 0);
        for(auto& [u,v] : items){ ++buf[u]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.m_list.resize(buf[n]);
        for(int i=(int)items.size()-1; i>=0; i--){
            res.m_list[--buf[items[i].first]] = std::move(items[i].second);
        }
        res.m_pos = std::move(buf);
        return res;
    }
    static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
        CsrArray res;
        res.m_n = pos.size() - 1;
        res.m_list = std::move(list);
        res.m_pos = std::move(pos);
        return res;
    }
    ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    int size() const { return m_n; }
    int fullSize() const { return (int)m_list.size(); }
};

} // namespace nachia

namespace nachia{


struct Graph {
public:
    struct Edge{
        int from, to;
        void reverse(){ std::swap(from, to); }
        int xorval() const { return from ^ to; }
    };
    Graph() : m_n(0), m_e(0), m_isUndir(false) {}
    explicit Graph(int n, bool undirected = false, int m = 0) : m_n(n), m_e(m), m_isUndir(undirected) {}
    explicit Graph(int n, const std::vector<std::pair<int, int>>& edges, int undirected = false) : m_n(n), m_isUndir(undirected){
        m_e.resize(edges.size());
        for(std::size_t i=0; i<edges.size(); i++) m_e[i] = { edges[i].first, edges[i].second };
    }
    template<class Cin>
    static Graph Input(Cin& cin, int n, bool undirected, int m, int offset = 0){
        Graph res(n, undirected, m);
        for(int i=0; i<m; i++){
            int u, v; cin >> u >> v;
            res[i].from = u - offset;
            res[i].to = v - offset;
        }
        return res;
    }
    int numVertices() const noexcept { return m_n; }
    int numEdges() const noexcept { return int(m_e.size()); }
    int addNode() noexcept { return m_n++; }
    int addEdge(int from, int to){ m_e.push_back({ from, to }); return numEdges() - 1; }
    Edge& operator[](int ei) noexcept { return m_e[ei]; }
    const Edge& operator[](int ei) const noexcept { return m_e[ei]; }
    Edge& at(int ei) { return m_e.at(ei); }
    const Edge& at(int ei) const { return m_e.at(ei); }
    auto begin(){ return m_e.begin(); }
    auto end(){ return m_e.end(); }
    auto begin() const { return m_e.begin(); }
    auto end() const { return m_e.end(); }
    bool isUndirected() const noexcept { return m_isUndir; }
    void reverseEdges() noexcept { for(auto& e : m_e) e.reverse(); }
    void contract(int newV, const std::vector<int>& mapping){
        assert(numVertices() == int(mapping.size()));
        for(int i=0; i<numVertices(); i++) assert(0 <= mapping[i] && mapping[i] < newV);
        for(auto& e : m_e){ e.from = mapping[e.from]; e.to = mapping[e.to]; }
        m_n = newV;
    }
    std::vector<Graph> induce(int num, const std::vector<int>& mapping) const {
        int n = numVertices();
        assert(n == int(mapping.size()));
        for(int i=0; i<n; i++) assert(-1 <= mapping[i] && mapping[i] < num);
        std::vector<int> indexV(n), newV(num);
        for(int i=0; i<n; i++) if(mapping[i] >= 0) indexV[i] = newV[mapping[i]]++;
        std::vector<Graph> res; res.reserve(num);
        for(int i=0; i<num; i++) res.emplace_back(newV[i], isUndirected());
        for(auto e : m_e) if(mapping[e.from] == mapping[e.to] && mapping[e.to] >= 0) res[mapping[e.to]].addEdge(indexV[e.from], indexV[e.to]);
        return res;
    }
    CsrArray<int> getEdgeIndexArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(int i=0; i<numEdges(); i++){
            auto e = operator[](i);
            src.emplace_back(e.from, i);
            if(undirected) src.emplace_back(e.to, i);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getEdgeIndexArray() const { return getEdgeIndexArray(isUndirected()); }
    CsrArray<int> getAdjacencyArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(auto e : m_e){
            src.emplace_back(e.from, e.to);
            if(undirected) src.emplace_back(e.to, e.from);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getAdjacencyArray() const { return getAdjacencyArray(isUndirected()); }
private:
    int m_n;
    std::vector<Edge> m_e;
    bool m_isUndir;
};

} // namespace nachia

namespace nachia{

struct HeavyLightDecomposition{
private:

    int N;
    std::vector<int> P;
    std::vector<int> PP;
    std::vector<int> PD;
    std::vector<int> D;
    std::vector<int> I;

    std::vector<int> rangeL;
    std::vector<int> rangeR;

public:
    
    HeavyLightDecomposition(const Graph& tree, int root = 0) {
        N = tree.numVertices();
        D.assign(N, 0); D[root] = 2;
        P.assign(N, 0);
        for(auto [u,v] : tree){ D[u] += 1; D[v] += 1; P[u] ^= v; P[v] ^= u; }

        std::vector<int> sz(N, 1);
        std::vector<int> top(N);
        std::vector<int> nx(N, -1);
        int ipos = 0;
        for(int v=0; v<N; v++) if(D[v] == 1) top[N-1-ipos++] = v;

        for(int i=0; i<ipos; i++){
            int v = top[N-1-i];
            if(--D[P[v]] == 1) top[N-1-ipos++] = P[v];
            P[P[v]] ^= v; sz[P[v]] += sz[v];
            if(nx[P[v]] == -1 || sz[nx[P[v]]] < sz[v]) nx[P[v]] = v;
        }
        assert(ipos == N-1 && "HLD input tree traverse failed");
        top[0] = root;
        P[root] = -1;

        PP.resize(N); for(int i=0; i<N; i++) PP[i] = i;
        for(int v : top) if(nx[v] != -1) PP[nx[v]] = PP[v];

        D.assign(N, 0);
        for(int v : top) if(v != root) D[v] = D[P[v]]+1;

        PD.assign(N,N); PD[root] = 0;
        for(int v : top) if(v != root) PD[v] = std::min(PD[PP[v]], PD[P[v]]+1);
        
        rangeL.assign(N,0);
        sz[root] = 1;
        for(int v : top){
            if(v != root && PP[v] == v){
                int p = P[v];
                rangeL[v] = sz[p];
                sz[p] += sz[v];
                sz[v] = rangeL[v] + 1;
            }
            int w = nx[v];
            if(w >= 0){
                rangeL[w] = sz[v];
                sz[v] += sz[w];
                sz[w] = rangeL[w] + 1;
            }
        }
        rangeR = std::move(sz);

        for(int i=0; i<N; i++) top[rangeL[i]] = i;
        I = std::move(top);
    }

    int numVertices() const { return N; }
    int depth(int p) const { return D[p]; }
    int toSeq(int vtx) const { return rangeL[vtx]; }
    int toVtx(int seqidx) const { return I[seqidx]; }
    int toSeq2In(int vtx) const { return rangeL[vtx] * 2 - D[vtx]; }
    int toSeq2Out(int vtx) const { return rangeR[vtx] * 2 - D[vtx] - 1; }
    int parentOf(int v) const { return P[v]; }
    int heavyRootOf(int v) const { return PP[v]; }
    int heavyChildOf(int v) const {
        if(toSeq(v) == N-1) return -1;
        int cand = toVtx(toSeq(v) + 1);
        if(PP[v] == PP[cand]) return cand;
        return -1;
    }

    int lca(int u, int v) const {
        if(PD[u] < PD[v]) std::swap(u, v);
        while(PD[u] > PD[v]) u = P[PP[u]];
        while(PP[u] != PP[v]){ u = P[PP[u]]; v = P[PP[v]]; }
        return (D[u] > D[v]) ? v : u;
        /*
        if(rangeL[u] > rangeL[v]) std::swap(u, v);
        int h = rangeL[u];
        while(h < rangeL[PP[v]]){ v = P[PP[v]]; }
        return rangeL[v] <= h ? v : u;
        */
    }

    int dist(int u, int v) const {
        return depth(u) + depth(v) - depth(lca(u,v)) * 2;
    }

    struct Range{
        int l; int r;
        int size() const { return r-l; }
        bool includes(int x) const { return l <= x && x < r; }
    };

    std::vector<Range> path(int r, int c, bool include_root = true, bool reverse_path = false) const {
        if(PD[c] < PD[r]) return {};
        std::vector<Range> res(PD[c]-PD[r]+1);
        for(int i=0; i<(int)res.size()-1; i++){
            res[i] = { rangeL[PP[c]], rangeL[c]+1 };
            c = P[PP[c]];
        }
        if(PP[r] != PP[c] || D[r] > D[c]) return {};
        res.back() = { rangeL[r]+(include_root?0:1), rangeL[c]+1 };
        if(res.back().l == res.back().r) res.pop_back();
        if(!reverse_path) std::reverse(res.begin(),res.end());
        else for(auto& a : res) a = { N - a.r, N - a.l };
        return res;
    }

    Range subtree(int p) const { return { rangeL[p], rangeR[p] }; }

    int median(int x, int y, int z) const {
        return lca(x,y) ^ lca(y,z) ^ lca(x,z);
    }

    int la(int from, int to, int d) const {
        if(d < 0) return -1;
        int g = lca(from,to);
        int dist0 = D[from] - D[g] * 2 + D[to];
        if(dist0 < d) return -1;
        int p = from;
        if(D[from] - D[g] < d){ p = to; d = dist0 - d; }
        while(D[p] - D[PP[p]] < d){
            d -= D[p] - D[PP[p]] + 1;
            p = P[PP[p]];
        }
        return I[rangeL[p] - d];
    }

    struct ChildrenIterRange {
    struct Iter {
        const HeavyLightDecomposition& hld; int s;
        int operator*() const { return hld.toVtx(s); }
        Iter& operator++(){
            s += hld.subtree(hld.I[s]).size();
            return *this;
        }
        Iter operator++(int) const { auto a = *this; return ++a; }
        bool operator==(Iter& r) const { return s == r.s; }
        bool operator!=(Iter& r) const { return s != r.s; }
    };
        const HeavyLightDecomposition& hld; int v;
        Iter begin() const { return { hld, hld.rangeL[v] + 1 }; }
        Iter end() const { return { hld, hld.rangeR[v] }; }
    };
    ChildrenIterRange children(int v) const {
        return ChildrenIterRange{ *this, v };
    }
};

} // namespace nachia

struct BIT {
  V<ll> A;
  BIT(ll n = 0) : A(n+1, 0) {}
  ll sum(ll r){
    ll x = 0;
    while(r > 0){ x += A[r]; r -= r & -r; }
    return x;
  }
  ll sum(ll l, ll r){ return sum(r) - sum(l); }
  void add(ll p, ll v){
    p += 1;
    while(p < ll(A.size())){
      A[p] += v;
      p += p& -p;
    }
  }
};

void testcase(){
  ll N; cin >> N;
  auto tree = nachia::Graph(N, 1);
  V<ll> depth(N), par(N);
  for(ll i=1; i<N; i++){
    ll p, d; cin >> p >> d; p--;
    depth[i] = d;
    par[i] = p;
    tree.addEdge(p, i);
  }
  V<V<ll>> P(20, V<ll>(N)); P[0] = par;
  REP(d,19) REP(i,N) P[d+1][i] = P[d][P[d][i]];
  auto hld = nachia::HeavyLightDecomposition(tree, 0);
  for(ll i=1; i<N; i++) depth[hld.toVtx(i)] += depth[par[hld.toVtx(i)]];
  BIT ds(N);
  ll z = 1;
  ll cent = 0;
  ll sumdist = 0;
  auto sumsubtree = [&](ll v) -> ll {
    auto [l,r] = hld.subtree(v);
    return ds.sum(l, r);
  };
  auto findcent = [&](ll v) -> ll {
    for(ll d=19; d>=0; d--) if(sumsubtree(P[d][v]) * 2 < z) v = P[d][v];
    return sumsubtree(v) * 2 < z ? par[v] : v;
  };
  auto sumsubtree2 = [&](ll v, ll root) -> ll {
    if(v == root || !hld.subtree(v).includes(hld.toSeq(root))) return sumsubtree(v);
    return z - sumsubtree(hld.la(v, root, 1));
  };
  auto farroot = [&](ll u, ll v) -> ll { return depth[u] < depth[v] ? v : u; };
  auto wdist = [&](ll u, ll v) -> ll {
    ll g = hld.lca(u, v);
    return depth[u] + depth[v] - 2 * depth[g];
  };
  ds.add(0,1);
  cout << 0 << "\n";
  for(ll k=1; k<N; k++){
    ds.add(hld.toSeq(k), 1); z++;
    sumdist += wdist(k, cent);
    ll newcent = farroot(findcent(k), findcent(cent));
    sumdist += (sumsubtree2(cent, newcent) * 2 - z) * wdist(cent, newcent);
    cent = newcent;
    cout << sumdist << "\n";
  }
}

int main(){
  cin.tie(0)->sync_with_stdio(0);
  testcase();
  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 47208
final_rank: 3

code_snippet: // AOJ #2636 Distance Sum
// 2025.3.21

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

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

void Cout(ll n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

const int MAX_NODES = 200005;
const int LOG_N = 19;

int parent[LOG_N][MAX_NODES];
int timeIn[MAX_NODES], timeOut[MAX_NODES], eulerTour[MAX_NODES];
int currentTime = -1;
int currentCenter = 0;
bool visited[MAX_NODES];
ll depth[MAX_NODES];
vector<pair<int, int>> treeAdj[MAX_NODES];


void dfs(int u) {
    timeIn[u] = ++currentTime;
    eulerTour[currentTime] = u;
    for (int i = 1; i < LOG_N; i++) parent[i][u] = parent[i-1][parent[i-1][u]];
    for (auto [child, weight] : treeAdj[u]) {
        parent[0][child] = u;
        depth[child] = depth[u] + weight;
        dfs(child);
    }
    timeOut[u] = currentTime;
}

bool isAncestor(int u, int v) {
    return timeIn[u] <= timeIn[v] && timeOut[v] <= timeOut[u];
}

int lca(int u, int v) {
    if (timeIn[u] > timeIn[v]) swap(u, v);
    if (isAncestor(u, v)) return u;
    for (int i = LOG_N - 1; i >= 0; i--) {
        if (!isAncestor(parent[i][u], v)) u = parent[i][u];
    }
    return parent[0][u];
}

ll distanceBetween(int u, int v) { return depth[u]+depth[v]-2*depth[lca(u, v)]; }


template <class S, S (*op)(S, S), S (*e)()>
class segtree {
public:
    segtree() : segtree(0) {}
    explicit segtree(int n) : _n(n) {
        log = 0;
        while ((1 << log) < _n) log++;
        size = 1 << log;
        d.assign(2 * size, e());
    }
    explicit segtree(const vector<S>& v) : segtree((int)v.size()) {
        for (int i = 0; i < (int)v.size(); i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) update(i);
    }
    void set(int p, S x) {
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    S get(int p) { return d[p + size]; }
    S prod(int l, int r) {
        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 /= 2;
            r /= 2;
        }
        return op(sml, smr);
    }
    S all_prod() { return d[1]; }
    template <class F>
    int max_right(int l, F f) {
        if (l == _n) return _n;
        S sm = e();
        l += size;
        do {
            while (l % 2 == 0) l /= 2;
            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 <class F>
    int min_left(int r, F f) {
        if (r == 0) return 0;
        S sm = e();
        r += size;
        do {
            r--;
            while (r > 1 && r % 2) r /= 2;
            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;
    vector<S> d;
    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};


using SegData = array<int, 2>;

SegData segOperation(SegData a, SegData b) { return { max(a[0], b[0]), a[1] + b[1] }; }

SegData segIdentity() { return { -1, 0 }; }

int main() {
    int N = Cin();
    for (int i = 1; i < N; i++) {
        int p = Cin()-1, d = Cin();
        treeAdj[p].emplace_back(i, d);
    }
    depth[0] = 0;
    parent[0][0] = 0;
    dfs(0);

    segtree<SegData, segOperation, segIdentity> segTree(N);

    ll ans = 0;
    fill(visited, visited + N, false);
    visited[0] = true;

    for (int i = 0, j; i < N; i++) {
        ans += distanceBetween(i, currentCenter);
        segTree.set(timeIn[i], { timeOut[i], 1 });

        for (j = i; !visited[j]; j = parent[0][j]) visited[j] = true;
        segTree.set(timeIn[j], { timeOut[j], (j <= i) ? 1 : 0 });

        int countInSubtree = segTree.prod(timeIn[currentCenter], timeOut[currentCenter] + 1)[1];
        if (countInSubtree * 2 < i + 1) {
            int newCenterIndex = segTree.min_left(timeIn[currentCenter], [&](SegData x) {
                return x[0] < timeOut[currentCenter];
            }) - 1;
            int newCenter = eulerTour[newCenterIndex];
            ans -= distanceBetween(newCenter, currentCenter);
            currentCenter = newCenter;
        }
        else if (currentCenter != i && isAncestor(currentCenter, i)) {
            int candidateIndex = segTree.max_right(timeIn[currentCenter] + 1, [&](SegData x) {
                return x[0] < timeOut[i];
            });
            int candidate = eulerTour[candidateIndex];
            if (segTree.prod(timeIn[candidate], timeOut[candidate] + 1)[1] * 2 > i + 1) {
                ans -= distanceBetween(candidate, currentCenter);
                currentCenter = candidate;
            }
        }
        Cout(ans);
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 45176
final_rank: 2

code_snippet: #line 1 "main.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2636"
#line 1 "library/my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;

using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;

#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll

int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T, typename U>
T ceil(T x, U y) {
  return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U>
T floor(T x, U y) {
  return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T, typename U>
pair<T, T> divmod(T x, U y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template <typename T, typename U>
T SUM(const vector<U> &A) {
  T sum = 0;
  for (auto &&a: A) sum += a;
  return sum;
}

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()


template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
  }
  return ok;
}
template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
  FOR(iter) {
    double x = (ok + ng) / 2;
    tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
  }
  return (ok + ng) / 2;
}

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

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vector<T> cumsum(vector<U> &A, int off = 1) {
  int N = A.size();
  vector<T> B(N + 1);
  FOR(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vector<int> argsort(const vector<T> &A) {
  vector<int> ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
  vc<T> B(len(I));
  FOR(i, len(I)) B[i] = A[I[i]];
  return B;
}
#endif
#line 1 "library/other/io.hpp"
// based on yosupo's fastio
#include <unistd.h>

namespace fastio {
#define FASTIO
// クラスが read(), print() を持っているかを判定するメタ関数
struct has_write_impl {
  template <class T>
  static auto check(T &&x) -> decltype(x.write(), std::true_type{});

  template <class T>
  static auto check(...) -> std::false_type;
};

template <class T>
class has_write : public decltype(has_write_impl::check<T>(std::declval<T>())) {
};

struct has_read_impl {
  template <class T>
  static auto check(T &&x) -> decltype(x.read(), std::true_type{});

  template <class T>
  static auto check(...) -> std::false_type;
};

template <class T>
class has_read : public decltype(has_read_impl::check<T>(std::declval<T>())) {};

struct Scanner {
  FILE *fp;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;
  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\0';
  }
  bool succ() {
    while (true) {
      if (st == ed) {
        reread();
        if (st == ed) return false;
      }
      while (st != ed && isspace(line[st])) st++;
      if (st != ed) break;
    }
    if (ed - st <= 50) {
      bool sep = false;
      for (size_t i = st; i < ed; i++) {
        if (isspace(line[i])) {
          sep = true;
          break;
        }
      }
      if (!sep) reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ()) return false;
    while (true) {
      size_t sz = 0;
      while (st + sz < ed && !isspace(line[st + sz])) sz++;
      ref.append(line + st, sz);
      st += sz;
      if (!sz || st != ed) break;
      reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ()) return false;
    bool neg = false;
    if (line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while (isdigit(line[st])) { ref = 10 * ref + (line[st++] & 0xf); }
    if (neg) ref = -ref;
    return true;
  }
  template <typename T,
            typename enable_if<has_read<T>::value>::type * = nullptr>
  inline bool read_single(T &x) {
    x.read();
    return true;
  }
  bool read_single(double &ref) {
    string s;
    if (!read_single(s)) return false;
    ref = std::stod(s);
    return true;
  }
  bool read_single(char &ref) {
    string s;
    if (!read_single(s) || s.size() != 1) return false;
    ref = s[0];
    return true;
  }
  template <class T>
  bool read_single(vector<T> &ref) {
    for (auto &d: ref) {
      if (!read_single(d)) return false;
    }
    return true;
  }
  template <class T, class U>
  bool read_single(pair<T, U> &p) {
    return (read_single(p.first) && read_single(p.second));
  }
  template <size_t N = 0, typename T>
  void read_single_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
      auto &x = std::get<N>(t);
      read_single(x);
      read_single_tuple<N + 1>(t);
    }
  }
  template <class... T>
  bool read_single(tuple<T...> &tpl) {
    read_single_tuple(tpl);
    return true;
  }
  void read() {}
  template <class H, class... T>
  void read(H &h, T &... t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }
  Scanner(FILE *fp) : fp(fp) {}
};

struct Printer {
  Printer(FILE *_fp) : fp(_fp) {}
  ~Printer() { flush(); }

  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;
  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }
  void write(const char val) {
    if (pos == SIZE) flush();
    line[pos++] = val;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  void write(T val) {
    if (pos > (1 << 15) - 50) flush();
    if (val == 0) {
      write('0');
      return;
    }
    if (val < 0) {
      write('-');
      val = -val; // todo min
    }
    size_t len = 0;
    while (val) {
      small[len++] = char(0x30 | (val % 10));
      val /= 10;
    }
    for (size_t i = 0; i < len; i++) { line[pos + i] = small[len - 1 - i]; }
    pos += len;
  }
  void write(const string s) {
    for (char c: s) write(c);
  }
  void write(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++) write(s[i]);
  }
  void write(const double x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << x;
    string s = oss.str();
    write(s);
  }
  void write(const long double x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << x;
    string s = oss.str();
    write(s);
  }
  template <typename T,
            typename enable_if<has_write<T>::value>::type * = nullptr>
  inline void write(T x) {
    x.write();
  }
  template <class T>
  void write(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write(' ');
      write(val[i]);
    }
  }
  template <class T, class U>
  void write(const pair<T, U> val) {
    write(val.first);
    write(' ');
    write(val.second);
  }
  template <size_t N = 0, typename T>
  void write_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
      if constexpr (N > 0) { write(' '); }
      const auto x = std::get<N>(t);
      write(x);
      write_tuple<N + 1>(t);
    }
  }
  template <class... T>
  bool write(tuple<T...> tpl) {
    write_tuple(tpl);
    return true;
  }
  template <class T, size_t S>
  void write(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write(' ');
      write(val[i]);
    }
  }
  void write(i128 val) {
    string s;
    bool negative = 0;
    if (val < 0) {
      negative = 1;
      val = -val;
    }
    while (val) {
      s += '0' + int(val % 10);
      val /= 10;
    }
    if (negative) s += "-";
    reverse(all(s));
    if (len(s) == 0) s = "0";
    write(s);
  }
};
Scanner scanner = Scanner(stdin);
Printer printer = Printer(stdout);
void flush() { printer.flush(); }
void print() { printer.write('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  printer.write(head);
  if (sizeof...(Tail)) printer.write(' ');
  print(forward<Tail>(tail)...);
}

void read() {}
template <class Head, class... Tail>
void read(Head &head, Tail &... tail) {
  scanner.read(head);
  read(tail...);
}
} // namespace fastio
using fastio::print;
using fastio::flush;
using fastio::read;

#define INT(...)   \
  int __VA_ARGS__; \
  read(__VA_ARGS__)
#define LL(...)   \
  ll __VA_ARGS__; \
  read(__VA_ARGS__)
#define STR(...)      \
  string __VA_ARGS__; \
  read(__VA_ARGS__)
#define CHAR(...)   \
  char __VA_ARGS__; \
  read(__VA_ARGS__)
#define DBL(...)      \
  double __VA_ARGS__; \
  read(__VA_ARGS__)

#define VEC(type, name, size) \
  vector<type> name(size);    \
  read(name)
#define VV(type, name, h, w)                     \
  vector<vector<type>> name(h, vector<type>(w)); \
  read(name)

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
#line 4 "main.cpp"

#line 2 "library/alg/monoid/add.hpp"

template <typename X>
struct Monoid_Add {
  using value_type = X;
  static constexpr X op(const X &x, const X &y) noexcept { return x + y; }
  static constexpr X inverse(const X &x) noexcept { return -x; }
  static constexpr X power(const X &x, ll n) noexcept { return X(n) * x; }
  static constexpr X unit() { return X(0); }
  static constexpr bool commute = true;
};
#line 3 "library/ds/fenwicktree/fenwicktree.hpp"

template <typename Monoid>
struct FenwickTree {
  using G = Monoid;
  using E = typename G::value_type;
  int n;
  vector<E> dat;
  E total;

  FenwickTree() {}
  FenwickTree(int n) { build(n); }
  template <typename F>
  FenwickTree(int n, F f) {
    build(n, f);
  }
  FenwickTree(const vc<E>& v) { build(v); }

  void build(int m) {
    n = m;
    dat.assign(m, G::unit());
    total = G::unit();
  }
  void build(const vc<E>& v) {
    build(len(v), [&](int i) -> E { return v[i]; });
  }
  template <typename F>
  void build(int m, F f) {
    n = m;
    dat.clear();
    dat.reserve(n);
    total = G::unit();
    FOR(i, n) { dat.eb(f(i)); }
    for (int i = 1; i <= n; ++i) {
      int j = i + (i & -i);
      if (j <= n) dat[j - 1] = G::op(dat[i - 1], dat[j - 1]);
    }
    total = prefix_sum(m);
  }

  E prod_all() { return total; }
  E sum_all() { return total; }
  E sum(int k) { return prefix_sum(k); }
  E prod(int k) { return prefix_prod(k); }
  E prefix_sum(int k) { return prefix_prod(k); }
  E prefix_prod(int k) {
    chmin(k, n);
    E ret = G::unit();
    for (; k > 0; k -= k & -k) ret = G::op(ret, dat[k - 1]);
    return ret;
  }
  E sum(int L, int R) { return prod(L, R); }
  E prod(int L, int R) {
    chmax(L, 0), chmin(R, n);
    if (L == 0) return prefix_prod(R);
    assert(0 <= L && L <= R && R <= n);
    E pos = G::unit(), neg = G::unit();
    while (L < R) { pos = G::op(pos, dat[R - 1]), R -= R & -R; }
    while (R < L) { neg = G::op(neg, dat[L - 1]), L -= L & -L; }
    return G::op(pos, G::inverse(neg));
  }

  void add(int k, E x) { multiply(k, x); }
  void multiply(int k, E x) {
    static_assert(G::commute);
    total = G::op(total, x);
    for (++k; k <= n; k += k & -k) dat[k - 1] = G::op(dat[k - 1], x);
  }

  template <class F>
  int max_right(const F check) {
    assert(check(G::unit()));
    int i = 0;
    E s = G::unit();
    int k = 1;
    while (2 * k <= n) k *= 2;
    while (k) {
      if (i + k - 1 < len(dat)) {
        E t = G::op(s, dat[i + k - 1]);
        if (check(t)) { i += k, s = t; }
      }
      k >>= 1;
    }
    return i;
  }

  int kth(E k) {
    return max_right([&k](E x) -> bool { return x <= k; });
  }
};
#line 2 "library/graph/tree.hpp"

#line 2 "library/graph/base.hpp"

template <typename T>
struct Edge {
  int frm, to;
  T cost;
  int id;
};

template <typename T = int, bool directed = false>
struct Graph {
  int N, M;
  using cost_type = T;
  using edge_type = Edge<T>;
  vector<edge_type> edges;
  vector<int> indptr;
  vector<edge_type> csr_edges;
  vc<int> vc_deg, vc_indeg, vc_outdeg;
  bool prepared;

  class OutgoingEdges {
  public:
    OutgoingEdges(const Graph* G, int l, int r) : G(G), l(l), r(r) {}

    const edge_type* begin() const {
      if (l == r) { return 0; }
      return &G->csr_edges[l];
    }

    const edge_type* end() const {
      if (l == r) { return 0; }
      return &G->csr_edges[r];
    }

  private:
    const Graph* G;
    int l, r;
  };

  bool is_prepared() { return prepared; }
  constexpr bool is_directed() { return directed; }

  Graph() : N(0), M(0), prepared(0) {}
  Graph(int N) : N(N), M(0), prepared(0) {}

  void build(int n) {
    N = n, M = 0;
    prepared = 0;
    edges.clear();
    indptr.clear();
    csr_edges.clear();
    vc_deg.clear();
    vc_indeg.clear();
    vc_outdeg.clear();
  }

  void add(int frm, int to, T cost = 1, int i = -1) {
    assert(!prepared);
    assert(0 <= frm && 0 <= to && to < N);
    if (i == -1) i = M;
    auto e = edge_type({frm, to, cost, i});
    edges.eb(e);
    ++M;
  }

  // wt, off
  void read_tree(bool wt = false, int off = 1) { read_graph(N - 1, wt, off); }

  void read_graph(int M, bool wt = false, int off = 1) {
    for (int m = 0; m < M; ++m) {
      INT(a, b);
      a -= off, b -= off;
      if (!wt) {
        add(a, b);
      } else {
        T c;
        read(c);
        add(a, b, c);
      }
    }
    build();
  }

  void read_parent(int off = 1) {
    for (int v = 1; v < N; ++v) {
      INT(p);
      p -= off;
      add(p, v);
    }
    build();
  }

  void build() {
    assert(!prepared);
    prepared = true;
    indptr.assign(N + 1, 0);
    for (auto&& e: edges) {
      indptr[e.frm + 1]++;
      if (!directed) indptr[e.to + 1]++;
    }
    for (int v = 0; v < N; ++v) { indptr[v + 1] += indptr[v]; }
    auto counter = indptr;
    csr_edges.resize(indptr.back() + 1);
    for (auto&& e: edges) {
      csr_edges[counter[e.frm]++] = e;
      if (!directed)
        csr_edges[counter[e.to]++] = edge_type({e.to, e.frm, e.cost, e.id});
    }
  }

  OutgoingEdges operator[](int v) const {
    assert(prepared);
    return {this, indptr[v], indptr[v + 1]};
  }

  vc<int> deg_array() {
    if (vc_deg.empty()) calc_deg();
    return vc_deg;
  }

  pair<vc<int>, vc<int>> deg_array_inout() {
    if (vc_indeg.empty()) calc_deg_inout();
    return {vc_indeg, vc_outdeg};
  }

  int deg(int v) {
    if (vc_deg.empty()) calc_deg();
    return vc_deg[v];
  }

  int in_deg(int v) {
    if (vc_indeg.empty()) calc_deg_inout();
    return vc_indeg[v];
  }

  int out_deg(int v) {
    if (vc_outdeg.empty()) calc_deg_inout();
    return vc_outdeg[v];
  }

  void debug() {
    print("Graph");
    if (!prepared) {
      print("frm to cost id");
      for (auto&& e: edges) print(e.frm, e.to, e.cost, e.id);
    } else {
      print("indptr", indptr);
      print("frm to cost id");
      FOR(v, N) for (auto&& e: (*this)[v]) print(e.frm, e.to, e.cost, e.id);
    }
  }

  // G における頂点 V[i] が、新しいグラフで i になるようにする
  Graph<T, directed> rearrange(vc<int> V) {
    int n = len(V);
    map<int, int> MP;
    FOR(i, n) MP[V[i]] = i;
    Graph<T, directed> G(n);
    for (auto&& e: edges) {
      if (MP.count(e.frm) && MP.count(e.to)) {
        G.add(MP[e.frm], MP[e.to], e.cost);
      }
    }
    G.build();
    return G;
  }

private:
  void calc_deg() {
    assert(vc_deg.empty());
    vc_deg.resize(N);
    for (auto&& e: edges) vc_deg[e.frm]++, vc_deg[e.to]++;
  }

  void calc_deg_inout() {
    assert(vc_indeg.empty());
    vc_indeg.resize(N);
    vc_outdeg.resize(N);
    for (auto&& e: edges) { vc_indeg[e.to]++, vc_outdeg[e.frm]++; }
  }
};
#line 4 "library/graph/tree.hpp"

// HLD euler tour をとっていろいろ。
// 木以外、非連結でも dfs 順序や親がとれる。
template <typename GT>
struct Tree {
  using Graph_type = GT;
  GT &G;
  using WT = typename GT::cost_type;
  int N;
  vector<int> LID, RID, head, V, parent, VtoE;
  vc<int> depth;
  vc<WT> depth_weighted;

  Tree(GT &G, int r = 0, bool hld = 1) : G(G) { build(r, hld); }

  void build(int r = 0, bool hld = 1) {
    if (r == -1) return; // build を遅延したいとき
    N = G.N;
    LID.assign(N, -1), RID.assign(N, -1), head.assign(N, r);
    V.assign(N, -1), parent.assign(N, -1), VtoE.assign(N, -1);
    depth.assign(N, -1), depth_weighted.assign(N, 0);
    assert(G.is_prepared());
    int t1 = 0;
    dfs_sz(r, -1, hld);
    dfs_hld(r, t1);
  }

  void dfs_sz(int v, int p, bool hld) {
    auto &sz = RID;
    parent[v] = p;
    depth[v] = (p == -1 ? 0 : depth[p] + 1);
    sz[v] = 1;
    int l = G.indptr[v], r = G.indptr[v + 1];
    auto &csr = G.csr_edges;
    // 使う辺があれば先頭にする
    for (int i = r - 2; i >= l; --i) {
      if (hld && depth[csr[i + 1].to] == -1) swap(csr[i], csr[i + 1]);
    }
    int hld_sz = 0;
    for (int i = l; i < r; ++i) {
      auto e = csr[i];
      if (depth[e.to] != -1) continue;
      depth_weighted[e.to] = depth_weighted[v] + e.cost;
      VtoE[e.to] = e.id;
      dfs_sz(e.to, v, hld);
      sz[v] += sz[e.to];
      if (hld && chmax(hld_sz, sz[e.to]) && l < i) { swap(csr[l], csr[i]); }
    }
  }

  void dfs_hld(int v, int &times) {
    LID[v] = times++;
    RID[v] += LID[v];
    V[LID[v]] = v;
    bool heavy = true;
    for (auto &&e: G[v]) {
      if (depth[e.to] <= depth[v]) continue;
      head[e.to] = (heavy ? head[v] : e.to);
      heavy = false;
      dfs_hld(e.to, times);
    }
  }

  vc<int> heavy_path_at(int v) {
    vc<int> P = {v};
    while (1) {
      int a = P.back();
      for (auto &&e: G[a]) {
        if (e.to != parent[a] && head[e.to] == v) {
          P.eb(e.to);
          break;
        }
      }
      if (P.back() == a) break;
    }
    return P;
  }

  int e_to_v(int eid) {
    auto e = G.edges[eid];
    return (parent[e.frm] == e.to ? e.frm : e.to);
  }
  int v_to_e(int v) { return VtoE[v]; }

  int ELID(int v) { return 2 * LID[v] - depth[v]; }
  int ERID(int v) { return 2 * RID[v] - depth[v] - 1; }

  /* k: 0-indexed */
  int LA(int v, int k) {
    assert(k <= depth[v]);
    while (1) {
      int u = head[v];
      if (LID[v] - k >= LID[u]) return V[LID[v] - k];
      k -= LID[v] - LID[u] + 1;
      v = parent[u];
    }
  }
  int la(int u, int v) { return LA(u, v); }

  int LCA(int u, int v) {
    for (;; v = parent[head[v]]) {
      if (LID[u] > LID[v]) swap(u, v);
      if (head[u] == head[v]) return u;
    }
  }
  // root を根とした場合の lca
  int LCA_root(int u, int v, int root) {
    return LCA(u, v) ^ LCA(u, root) ^ LCA(v, root);
  }
  int lca(int u, int v) { return LCA(u, v); }
  int lca_root(int u, int v, int root) { return LCA_root(u, v, root); }

  int subtree_size(int v, int root = -1) {
    if (root == -1) return RID[v] - LID[v];
    if (v == root) return N;
    int x = jump(v, root, 1);
    if (in_subtree(v, x)) return RID[v] - LID[v];
    return N - RID[x] + LID[x];
  }

  int dist(int a, int b) {
    int c = LCA(a, b);
    return depth[a] + depth[b] - 2 * depth[c];
  }

  WT dist_weighted(int a, int b) {
    int c = LCA(a, b);
    return depth_weighted[a] + depth_weighted[b] - WT(2) * depth_weighted[c];
  }

  // a is in b
  bool in_subtree(int a, int b) { return LID[b] <= LID[a] && LID[a] < RID[b]; }

  int jump(int a, int b, ll k) {
    if (k == 1) {
      if (a == b) return -1;
      return (in_subtree(b, a) ? LA(b, depth[b] - depth[a] - 1) : parent[a]);
    }
    int c = LCA(a, b);
    int d_ac = depth[a] - depth[c];
    int d_bc = depth[b] - depth[c];
    if (k > d_ac + d_bc) return -1;
    if (k <= d_ac) return LA(a, k);
    return LA(b, d_ac + d_bc - k);
  }

  vc<int> collect_child(int v) {
    vc<int> res;
    for (auto &&e: G[v])
      if (e.to != parent[v]) res.eb(e.to);
    return res;
  }

  vc<pair<int, int>> get_path_decomposition(int u, int v, bool edge) {
    // [始点, 終点] の"閉"区間列。
    vc<pair<int, int>> up, down;
    while (1) {
      if (head[u] == head[v]) break;
      if (LID[u] < LID[v]) {
        down.eb(LID[head[v]], LID[v]);
        v = parent[head[v]];
      } else {
        up.eb(LID[u], LID[head[u]]);
        u = parent[head[u]];
      }
    }
    if (LID[u] < LID[v]) down.eb(LID[u] + edge, LID[v]);
    elif (LID[v] + edge <= LID[u]) up.eb(LID[u], LID[v] + edge);
    reverse(all(down));
    up.insert(up.end(), all(down));
    return up;
  }

  vc<int> restore_path(int u, int v) {
    vc<int> P;
    for (auto &&[a, b]: get_path_decomposition(u, v, 0)) {
      if (a <= b) {
        FOR(i, a, b + 1) P.eb(V[i]);
      } else {
        FOR_R(i, b, a + 1) P.eb(V[i]);
      }
    }
    return P;
  }
};
#line 3 "library/graph/ds/tree_abelgroup.hpp"

template <typename TREE, typename AbelGroup, bool edge, bool path_query,
          bool subtree_query>
struct Tree_AbelGroup {
  using X = typename AbelGroup::value_type;
  TREE &tree;
  int N;
  FenwickTree<AbelGroup> bit, bit_subtree;

  Tree_AbelGroup(TREE &tree) : tree(tree), N(tree.N) {
    build([](int i) -> X { return AbelGroup::unit(); });
  }

  Tree_AbelGroup(TREE &tree, vc<X> &dat) : tree(tree), N(tree.N) {
    build([&](int i) -> X { return dat[i]; });
  }

  template <typename F>
  Tree_AbelGroup(TREE &tree, F f) : tree(tree), N(tree.N) {
    build(f);
  }

  template <typename F>
  void build(F f) {
    vc<X> bit_raw_1(2 * N);
    vc<X> bit_raw_2(N);
    if (!edge) {
      FOR(v, N) {
        X x = f(v);
        bit_raw_1[tree.ELID(v)] = x;
        bit_raw_1[tree.ERID(v)] = AbelGroup::inverse(x);
        bit_raw_2[tree.LID[v]] = x;
      }
    } else {
      FOR(e, N - 1) {
        int v = tree.e_to_v(e);
        X x = f(v);
        bit_raw_1[tree.ELID(v)] = x;
        bit_raw_1[tree.ERID(v)] = AbelGroup::inverse(x);
        bit_raw_2[tree.LID[v]] = x;
      }
    }
    bit.build(bit_raw_1);
    bit_subtree.build(bit_raw_2);
  }

  void add(int i, X x) {
    int v = (edge ? tree.e_to_v(i) : i);
    if (path_query) {
      X inv_x = AbelGroup::inverse(x);
      bit.add(tree.ELID(v), x);
      bit.add(tree.ERID(v), inv_x);
    }
    if (subtree_query) bit_subtree.add(tree.LID[v], x);
  }

  X prod_path(int frm, int to) {
    assert(path_query);
    int lca = tree.LCA(frm, to);
    // [frm, lca)
    X x1 = bit.prod(tree.ELID(lca) + 1, tree.ELID(frm) + 1);
    // edge なら (lca, to]、vertex なら [lca, to]
    X x2 = bit.prod(tree.ELID(lca) + edge, tree.ELID(to) + 1);
    return AbelGroup::op(x1, x2);
  }

  X prod_subtree(int u) {
    assert(subtree_query);
    int l = tree.LID[u], r = tree.RID[u];
    return bit_subtree.prod(l + edge, r);
  }
};
#line 1 "library/ds/fastset.hpp"
/* 64分木。
insert, erase
[]での存在判定
next, prev
*/
struct FastSet {
  using uint = unsigned;
  using ull = unsigned long long;

  int bsr(ull x) { return 63 - __builtin_clzll(x); }
  int bsf(ull x) { return __builtin_ctzll(x); }

  static constexpr uint B = 64;
  int n, lg;
  vector<vector<ull>> seg;
  FastSet(int _n) : n(_n) {
    do {
      seg.push_back(vector<ull>((_n + B - 1) / B));
      _n = (_n + B - 1) / B;
    } while (_n > 1);
    lg = int(seg.size());
  }
  bool operator[](int i) const { return (seg[0][i / B] >> (i % B) & 1) != 0; }
  void insert(int i) {
    for (int h = 0; h < lg; h++) {
      seg[h][i / B] |= 1ULL << (i % B);
      i /= B;
    }
  }
  void erase(int i) {
    for (int h = 0; h < lg; h++) {
      seg[h][i / B] &= ~(1ULL << (i % B));
      if (seg[h][i / B]) break;
      i /= B;
    }
  }

  // x以上最小の要素を返す。存在しなければ n。
  int next(int i) {
    chmax(i, 0);
    if (i >= n) return n;
    for (int h = 0; h < lg; h++) {
      if (i / B == seg[h].size()) break;
      ull d = seg[h][i / B] >> (i % B);
      if (!d) {
        i = i / B + 1;
        continue;
      }
      // find
      i += bsf(d);
      for (int g = h - 1; g >= 0; g--) {
        i *= B;
        i += bsf(seg[g][i / B]);
      }
      return i;
    }
    return n;
  }

  // x以下最大の要素を返す。存在しなければ -1。
  int prev(int i) {
    if (i < 0) return -1;
    if (i >= n) i = n - 1;
    for (int h = 0; h < lg; h++) {
      if (i == -1) break;
      ull d = seg[h][i / B] << (63 - i % 64);
      if (!d) {
        i = i / B - 1;
        continue;
      }
      // find
      i += bsr(d) - (B - 1);
      for (int g = h - 1; g >= 0; g--) {
        i *= B;
        i += bsr(seg[g][i / B]);
      }
      return i;
    }
    return -1;
  }

  // [l, r)
  template <typename F>
  void enumerate(int l, int r, F f) {
    int x = l - 1;
    while (1) {
      x = next(x + 1);
      if (x >= r) break;
      f(x);
    }
  }

  void debug() {
    string s;
    for (int i = 0; i < n; ++i) s += ((*this)[i] ? '1' : '0');
    print(s);
  }
};
#line 3 "library/graph/ds/incremental_centroid.hpp"

// 木は固定。頂点重みを +1 できる。
// cent: 重心
// max_subtree
template <typename TREE>
struct Incremental_Centroid {
  TREE& tree;
  int N;
  int cent;
  pair<int, int> max_subtree; // (adj, size)
  int wt_sm;
  Tree_AbelGroup<TREE, Monoid_Add<int>, 0, 0, 1> TA;
  FastSet ss;

  Incremental_Centroid(TREE& tree)
      : tree(tree),
        N(tree.N),
        cent(0),
        max_subtree(0, 0),
        wt_sm(0),
        TA(tree),
        ss(N) {}

  int get_subtree_wt(int v) {
    assert(v != cent);
    // cent から見て v 方向
    if (tree.in_subtree(v, cent)) {
      return TA.prod_subtree(tree.jump(cent, v, 1));
    }
    return wt_sm - TA.prod_subtree(cent);
  }

  int move_to(int v) {
    // 圧縮木上で cent から v に進む
    if (tree.in_subtree(v, cent)) {
      // v 方向にある重みの lca
      int a = tree.jump(cent, v, 1);
      int L = tree.LID[a], R = tree.RID[a];
      L = ss.next(L), R = ss.prev(R - 1);
      int x = tree.V[L], y = tree.V[R];
      return tree.lca(x, y);
    }
    int L = tree.LID[cent], R = tree.RID[cent];
    int x = v;
    vc<int> I;
    I.eb(ss.next(0)), I.eb(ss.prev(L - 1));
    I.eb(ss.next(R)), I.eb(ss.prev(N - 1));
    for (auto&& idx: I) {
      if (idx == -1 || idx == N) continue;
      if (L <= idx && idx < R) continue;
      int y = tree.V[idx];
      x = tree.lca_root(x, y, cent);
    }
    return x;
  }

  void add(int v) {
    ss.insert(tree.LID[v]), TA.add(v, 1), wt_sm++;
    if (v == cent) return;
    int wt = get_subtree_wt(v);
    if (max_subtree.se < wt) max_subtree = {tree.jump(cent, v, 1), wt};
    if (2 * wt <= wt_sm) return;
    int k = wt;
    assert(wt_sm == 2 * k - 1);
    int to = move_to(v);
    max_subtree = {tree.jump(to, cent, 1), k - 1};
    cent = to;
  }
};
#line 6 "main.cpp"

void solve() {
  LL(N);
  Graph<ll, 1> G(N);
  FOR(v, 1, N) {
    LL(p, d);
    G.add(--p, v, d);
  }
  G.build();

  Tree<decltype(G)> tree(G);
  Incremental_Centroid<decltype(tree)> X(tree);

  ll ans = 0;

  FOR(v, N) {
    int cent = X.cent;
    X.add(v);
    int to = X.cent;
    ans += tree.dist_weighted(cent, v);
    ans -= tree.dist_weighted(cent, to);
    print(ans);
  }
}

signed main() {
  solve();
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 46912
final_rank: 1

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

using namespace std;

#define ov3(a, b, c, name, ...) name
#define ll long long
#define rep2(i, a, b) for(ll i = (a); i < (b); i++)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(iiiii, n)
#define rep(...) ov3(__VA_ARGS__, rep2, rep1, rep0)(__VA_ARGS__)
#define si(c) (ll)(c.size())
#define pll pair<ll, ll>
#define vl vector<ll>
#define all(v) v.begin(), v.end()
#define fore(e, v) for(auto &&e : v)

template <typename S, typename T> bool chmax(S &x, const T &y) { return (x < y ? x = y, true : false); }

template <typename S, typename T> bool chmin(S &x, const T &y) { return (x > y ? x = y, true : false); }

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << "{";
    rep(i, si(v)) {
        if(i) os << ", ";
        os << v[i];
    }
    return os << "}";
}

template <typename T, typename F> struct segtree {
    int n, rn;
    vector<T> seg;
    F f;
    T id;

    segtree() = default;

    segtree(int rn, F f, T id) : rn(rn), f(f), id(id) {
        n = 1;
        while(n < rn) n <<= 1;
        seg.assign(n * 2, id);
    }

    void set(int i, T x) { seg[i + n] = x; }

    void build() {
        for(int k = n - 1; k > 0; k--) seg[k] = f(seg[k * 2], seg[k * 2 + 1]);
    }

    void update(int i, T x) {
        set(i, x);
        i += n;
        while(i >>= 1) seg[i] = f(seg[i * 2], seg[i * 2 + 1]);
    }

    T get(int i) { return seg[i + n]; }

    T prod(int l, int r) {
        T L = id, R = id;
        for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if(l & 1) L = f(L, seg[l++]);
            if(r & 1) R = f(seg[--r], R);
        }
        return f(L, R);
    }

    template <typename C> int max_right(int l, const C &c) {
        assert(c(id));
        if(l >= rn) return rn;
        l += n;
        T sum = id;
        do {
            while((l & 1) == 0) l >>= 1;
            if(!c(f(sum, seg[l]))) {
                while(l < n) {
                    l <<= 1;
                    auto nxt = f(sum, seg[l]);
                    if(c(nxt)) {
                        sum = nxt;
                        l++;
                    }
                }
                return l - n;
            }
            sum = f(sum, seg[l++]);
        } while((l & -l) != l);
        return rn;
    }
};

template <typename G> struct HLD {
    int n;
    G &g;
    vector<int> sub, in, out, head, rev, par, d;

    HLD(G &g) : n(si(g)), g(g), sub(n), in(n), out(n), head(n), rev(n), par(n), d(n) {}

    void dfs1(int x, int p) {
        par[x] = p;
        sub[x] = 1;
        if(g[x].size() and g[x][0] == p) swap(g[x][0], g[x].back());
        fore(e, g[x]) {
            if(e == p) continue;
            d[e] = d[x] + 1;
            dfs1(e, x);
            sub[x] += sub[e];
            if(sub[g[x][0]] < sub[e]) swap(g[x][0], e);
        }
    }

    void dfs2(int x, int p, int &t) {
        in[x] = t++;
        rev[in[x]] = x;
        fore(e, g[x]) {
            if(e == p) continue;
            head[e] = (g[x][0] == e ? head[x] : e);
            dfs2(e, x, t);
        }
        out[x] = t;
    }

    void build() {
        int t = 0;
        head[0] = 0;
        dfs1(0, -1);
        dfs2(0, -1, t);
    }

    int la(int v, int k) {
        while(1) {
            int u = head[v];
            if(in[v] - k >= in[u]) return rev[in[v] - k];
            k -= in[v] - in[u] + 1;
            v = par[u];
        }
    }

    int lca(int u, int v) {
        for(;; v = par[head[v]]) {
            if(in[u] > in[v]) swap(u, v);
            if(head[u] == head[v]) return u;
        }
    }

    template <typename T, typename Q, typename F> T query(int u, int v, const T &e, const Q &q, const F &f, bool edge = false) {
        T l = e, r = e;
        for(;; v = par[head[v]]) {
            if(in[u] > in[v]) swap(u, v), swap(l, r);
            if(head[u] == head[v]) break;
            l = f(q(in[head[v]], in[v] + 1), l);
        }
        return f(f(q(in[u] + edge, in[v] + 1), l), r);
    }

    int dist(int u, int v) { return d[u] + d[v] - 2 * d[lca(u, v)]; }

    int jump(int s, int t, int i) {
        if(!i) return s;
        int l = lca(s, t);
        int dst = d[s] + d[t] - d[l] * 2;
        if(dst < i) return -1;
        if(d[s] - d[l] >= i) return la(s, i);
        i -= d[s] - d[l];
        return la(t, d[t] - d[l] - i);
    }
};

template <typename T> struct edge {
    int to;
    T cost;

    edge(int to, T cost) : to(to), cost(cost) {}

    edge &operator=(const int &x) {
        to = x;
        return *this;
    }

    operator int() const { return to; }
};

int main() {
    cin.tie(0), cout.tie(0);
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    vector<vector<edge<ll>>> g(n);
    rep(i, 1, n) {
        int x, c;
        cin >> x >> c;
        x--;
        g[x].emplace_back(i, c);
    }
    HLD hld(g);
    hld.build();

    ll sum = 0;
    int now = 0;
    cout << sum << "\n";

    vector<map<int, int>> G(n);
    set<int> s;
    s.emplace(0);

    vl par(n);

    auto connect = [&](int i, int j) {
        if(i == j) return;
        if(hld.d[i] < hld.d[j]) swap(i, j);
        par[i] = j;
        G[i][hld.jump(i, j, 1)] = j;
        G[j][hld.jump(j, i, 1)] = i;
    };

    vl d(n), dp(n);
    auto dfs = [&](auto &&f, int x) -> void {
        fore(e, g[x]) {
            d[e] = d[x] + e.cost;
            dp[e] = e.cost;
            f(f, e);
        }
    };
    dfs(dfs, 0);
    //    cout << d << endl;
    auto dist = [&](int i, int j) {
        int u = hld.lca(i, j);
        //        cout << "lca: " << i << " " << j << " " << u << endl;
        return d[i] + d[j] - d[u] * 2;
    };

    auto f = [](int x, int y) { return x + y; };
    segtree<int, decltype(f)> seg(n, f, 0);
    seg.update(0, 1);

    rep(i, 1, n) {
        int idx = hld.in[i];
        auto it = s.lower_bound(idx);
        int mypar;
        if(it != begin(s)) {
            int l = hld.rev[*prev(it)];
            int c = hld.lca(l, i);
            mypar = c;
            if(s.insert(hld.in[c]).second) {
                l = hld.rev[*s.lower_bound(hld.in[hld.jump(c, l, 1)])];
                int p = par[l];
                // cout << l << " " << c << " " << p << endl;
                connect(l, c);
                connect(i, c);
                connect(c, p);
            }
        }
        if(it != end(s)) {
            int r = hld.rev[*it];
            int c = hld.lca(r, i);
            if(hld.d[mypar] < hld.d[c]) mypar = c;
            if(s.insert(hld.in[c]).second) {
                r = hld.rev[*s.lower_bound(hld.in[hld.jump(c, r, 1)])];
                int p = par[r];
                connect(r, c);
                connect(i, c);
                connect(c, p);
            }
        }
        connect(i, mypar);
        s.insert(hld.in[i]);
        seg.update(hld.in[i], 1);
        //        cout << now << " " << dist(now, i) << endl;
        sum += dist(now, i);

        int cnt = 0;
        // cout << i << endl;
        // rep(i, n) if(!empty(G[i])) {
        //     cout << i << " :";
        //     fore(e, G[i]) cout << "(" << e.first << ", " << e.second << ")";
        //     cout << hld.d[i];
        //     cout << endl;
        // }
        // cout << "HLD:" << hld.in[i] << " " << hld.out[i] << endl;

        while(true) {
            cnt++;
            if(cnt > 2) assert(0);
            if(now == i) break;
            int nxt = hld.jump(now, i, 1);
            int to = G[now][nxt];
            ll s;
            if(hld.d[nxt] > hld.d[now]) {
                s = seg.prod(hld.in[to], hld.out[to]);
                // cout << "Q" << hld.in[to] << " " << hld.out[to] << endl;
            } else
                s = (i + 1) - seg.prod(hld.in[now], hld.out[now]);
            // cout << now << " " << nxt << " " << to << " " << s << endl;
            if(s > (i + 1 - s)) {
                assert(cnt == 1);
                sum -= dist(now, to) * (s * 2 - (i + 1));
                now = to;
            } else {
                break;
            }
        }
        cout << sum << '\n';
        // if(i == 4) break;
    }
}
accuracy: 1
time_ms: 340
memory_kb: 80076
final_rank: 4

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

using namespace std;

#define ov3(a, b, c, name, ...) name
#define ll long long
#define rep2(i, a, b) for(ll i = (a); i < (b); i++)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(iiiii, n)
#define rep(...) ov3(__VA_ARGS__, rep2, rep1, rep0)(__VA_ARGS__)
#define si(c) (ll)(c.size())
#define pll pair<ll, ll>
#define vl vector<ll>
#define all(v) v.begin(), v.end()
#define fore(e, v) for(auto &&e : v)

template <typename S, typename T> bool chmax(S &x, const T &y) { return (x < y ? x = y, true : false); }

template <typename S, typename T> bool chmin(S &x, const T &y) { return (x > y ? x = y, true : false); }

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << "{";
    rep(i, si(v)) {
        if(i) os << ", ";
        os << v[i];
    }
    return os << "}";
}

template <typename T, typename F> struct segtree {
    int n, rn;
    vector<T> seg;
    F f;
    T id;

    segtree() = default;

    segtree(int rn, F f, T id) : rn(rn), f(f), id(id) {
        n = 1;
        while(n < rn) n <<= 1;
        seg.assign(n * 2, id);
    }

    void set(int i, T x) { seg[i + n] = x; }

    void build() {
        for(int k = n - 1; k > 0; k--) seg[k] = f(seg[k * 2], seg[k * 2 + 1]);
    }

    void update(int i, T x) {
        set(i, x);
        i += n;
        while(i >>= 1) seg[i] = f(seg[i * 2], seg[i * 2 + 1]);
    }

    T get(int i) { return seg[i + n]; }

    T prod(int l, int r) {
        T L = id, R = id;
        for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if(l & 1) L = f(L, seg[l++]);
            if(r & 1) R = f(seg[--r], R);
        }
        return f(L, R);
    }

    template <typename C> int max_right(int l, const C &c) {
        assert(c(id));
        if(l >= rn) return rn;
        l += n;
        T sum = id;
        do {
            while((l & 1) == 0) l >>= 1;
            if(!c(f(sum, seg[l]))) {
                while(l < n) {
                    l <<= 1;
                    auto nxt = f(sum, seg[l]);
                    if(c(nxt)) {
                        sum = nxt;
                        l++;
                    }
                }
                return l - n;
            }
            sum = f(sum, seg[l++]);
        } while((l & -l) != l);
        return rn;
    }
};

template <typename G> struct HLD {
    int n;
    G &g;
    vector<int> sub, in, out, head, rev, par, d;

    HLD(G &g) : n(si(g)), g(g), sub(n), in(n), out(n), head(n), rev(n), par(n), d(n) {}

    void dfs1(int x, int p) {
        par[x] = p;
        sub[x] = 1;
        if(g[x].size() and g[x][0] == p) swap(g[x][0], g[x].back());
        fore(e, g[x]) {
            if(e == p) continue;
            d[e] = d[x] + 1;
            dfs1(e, x);
            sub[x] += sub[e];
            if(sub[g[x][0]] < sub[e]) swap(g[x][0], e);
        }
    }

    void dfs2(int x, int p, int &t) {
        in[x] = t++;
        rev[in[x]] = x;
        fore(e, g[x]) {
            if(e == p) continue;
            head[e] = (g[x][0] == e ? head[x] : e);
            dfs2(e, x, t);
        }
        out[x] = t;
    }

    void build() {
        int t = 0;
        head[0] = 0;
        dfs1(0, -1);
        dfs2(0, -1, t);
    }

    int la(int v, int k) {
        while(1) {
            int u = head[v];
            if(in[v] - k >= in[u]) return rev[in[v] - k];
            k -= in[v] - in[u] + 1;
            v = par[u];
        }
    }

    int lca(int u, int v) {
        for(;; v = par[head[v]]) {
            if(in[u] > in[v]) swap(u, v);
            if(head[u] == head[v]) return u;
        }
    }

    template <typename T, typename Q, typename F> T query(int u, int v, const T &e, const Q &q, const F &f, bool edge = false) {
        T l = e, r = e;
        for(;; v = par[head[v]]) {
            if(in[u] > in[v]) swap(u, v), swap(l, r);
            if(head[u] == head[v]) break;
            l = f(q(in[head[v]], in[v] + 1), l);
        }
        return f(f(q(in[u] + edge, in[v] + 1), l), r);
    }

    int dist(int u, int v) { return d[u] + d[v] - 2 * d[lca(u, v)]; }

    int jump(int s, int t, int i) {
        if(!i) return s;
        int l = lca(s, t);
        int dst = d[s] + d[t] - d[l] * 2;
        if(dst < i) return -1;
        if(d[s] - d[l] >= i) return la(s, i);
        i -= d[s] - d[l];
        return la(t, d[t] - d[l] - i);
    }
};

template <typename T> struct edge {
    int to;
    T cost;

    edge(int to, T cost) : to(to), cost(cost) {}

    edge &operator=(const int &x) {
        to = x;
        return *this;
    }

    operator int() const { return to; }
};

int main() {
    cin.tie(0), cout.tie(0);
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    vector<vector<edge<ll>>> g(n);
    rep(i, 1, n) {
        int x, c;
        cin >> x >> c;
        x--;
        g[x].emplace_back(i, c);
    }
    HLD hld(g);
    hld.build();

    ll sum = 0;
    int now = 0;
    cout << sum << "\n";

    vector<map<int, int>> G(n);
    set<int> s;
    s.emplace(0);

    vl par(n);

    auto connect = [&](int i, int j) {
        if(i == j) return;
        if(hld.d[i] < hld.d[j]) swap(i, j);
        par[i] = j;
        G[i][hld.jump(i, j, 1)] = j;
        G[j][hld.jump(j, i, 1)] = i;
    };

    vl d(n), dp(n);
    auto dfs = [&](auto &&f, int x) -> void {
        fore(e, g[x]) {
            d[e] = d[x] + e.cost;
            dp[e] = e.cost;
            f(f, e);
        }
    };
    dfs(dfs, 0);
    //    cout << d << endl;
    auto dist = [&](int i, int j) {
        int u = hld.lca(i, j);
        //        cout << "lca: " << i << " " << j << " " << u << endl;
        return d[i] + d[j] - d[u] * 2;
    };

    auto f = [](int x, int y) { return x + y; };
    segtree<int, decltype(f)> seg(n, f, 0);
    seg.update(0, 1);

    rep(i, 1, n) {
        int idx = hld.in[i];
        auto it = s.lower_bound(idx);
        int mypar;
        if(it != begin(s)) {
            int l = hld.rev[*prev(it)];
            int c = hld.lca(l, i);
            mypar = c;
            if(s.insert(hld.in[c]).second) {
                int p = par[l];
                connect(l, c);
                connect(i, c);
                connect(c, p);
            }
        }
        if(it != end(s)) {
            int r = hld.rev[*it];
            int c = hld.lca(r, i);
            if(hld.d[mypar] < hld.d[c]) mypar = c;
            if(s.insert(hld.in[c]).second) {
                int p = par[r];
                connect(r, c);
                connect(i, c);
                connect(c, p);
            }
        }
        connect(i, mypar);
        s.insert(hld.in[i]);
        seg.update(hld.in[i], 1);
        //        cout << now << " " << dist(now, i) << endl;
        sum += dist(now, i);

        int cnt = 0;
        // cout << i << endl;
        // rep(i, n) if(!empty(G[i])) {
        //     cout << i << " :";
        //     fore(e, G[i]) cout << "(" << e.first << ", " << e.second << ")";
        //     cout << endl;
        // }
        while(true) {
            cnt++;
            if(cnt > 2) assert(0);
            if(now == i) break;
            int nxt = hld.jump(now, i, 1);
            int to = G[now][nxt];
            ll s;
            if(hld.d[nxt] > hld.d[now])
                s = seg.prod(hld.in[to], hld.out[to]);
            else
                s = (i + 1) - seg.prod(hld.in[now], hld.out[now]);
            // cout << now << " " << nxt << " " << to << " " << s << endl;
            if(s > (i + 1 - s)) {
                sum -= dist(now, to) * (s * 2 - (i + 1));
                now = to;
            } else {
                break;
            }
        }
        cout << sum << '\n';
    }
}
accuracy: 0.35135135135135137
time_ms: 320
memory_kb: 75020
final_rank: 18

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

using namespace std;

#define ov3(a, b, c, name, ...) name
#define ll long long
#define rep2(i, a, b) for(ll i = (a); i < (b); i++)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(iiiii, n)
#define rep(...) ov3(__VA_ARGS__, rep2, rep1, rep0)(__VA_ARGS__)
#define si(c) (ll)(c.size())
#define pll pair<ll, ll>
#define vl vector<ll>
#define all(v) v.begin(), v.end()
#define fore(e, v) for(auto &&e : v)

template<typename S, typename T>
bool chmax(S &x, const T &y) { return (x < y ? x = y, true : false); }

template<typename S, typename T>
bool chmin(S &x, const T &y) { return (x > y ? x = y, true : false); }

template<typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    os << "{";
    rep(i, si(v)) {
        if (i) os << ", ";
        os << v[i];
    }
    return os << "}";
}

template<typename T, typename F>
struct segtree {
    int n, rn;
    vector<T> seg;
    F f;
    T id;

    segtree() = default;

    segtree(int rn, F f, T id) : rn(rn), f(f), id(id) {
        n = 1;
        while (n < rn) n <<= 1;
        seg.assign(n * 2, id);
    }

    void set(int i, T x) { seg[i + n] = x; }

    void build() {
        for (int k = n - 1; k > 0; k--) seg[k] = f(seg[k * 2], seg[k * 2 + 1]);
    }

    void update(int i, T x) {
        set(i, x);
        i += n;
        while (i >>= 1) seg[i] = f(seg[i * 2], seg[i * 2 + 1]);
    }

    T get(int i) { return seg[i + n]; }

    T prod(int l, int r) {
        T L = id, R = id;
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) L = f(L, seg[l++]);
            if (r & 1) R = f(seg[--r], R);
        }
        return f(L, R);
    }

    template<typename C>
    int max_right(int l, const C &c) {
        assert(c(id));
        if (l >= rn) return rn;
        l += n;
        T sum = id;
        do {
            while ((l & 1) == 0) l >>= 1;
            if (!c(f(sum, seg[l]))) {
                while (l < n) {
                    l <<= 1;
                    auto nxt = f(sum, seg[l]);
                    if (c(nxt)) {
                        sum = nxt;
                        l++;
                    }
                }
                return l - n;
            }
            sum = f(sum, seg[l++]);
        } while ((l & -l) != l);
        return rn;
    }
};


template<typename G>
struct HLD {
    int n;
    G &g;
    vector<int> sub, in, out, head, rev, par, d;

    HLD(G &g) : n(si(g)), g(g), sub(n), in(n), out(n), head(n), rev(n), par(n), d(n) {}

    void dfs1(int x, int p) {
        par[x] = p;
        sub[x] = 1;
        if (g[x].size() and g[x][0] == p) swap(g[x][0], g[x].back());
        fore(e, g[x]) {
            if (e == p) continue;
            d[e] = d[x] + 1;
            dfs1(e, x);
            sub[x] += sub[e];
            if (sub[g[x][0]] < sub[e]) swap(g[x][0], e);
        }
    }

    void dfs2(int x, int p, int &t) {
        in[x] = t++;
        rev[in[x]] = x;
        fore(e, g[x]) {
            if (e == p) continue;
            head[e] = (g[x][0] == e ? head[x] : e);
            dfs2(e, x, t);
        }
        out[x] = t;
    }

    void build() {
        int t = 0;
        head[0] = 0;
        dfs1(0, -1);
        dfs2(0, -1, t);
    }

    int la(int v, int k) {
        while (1) {
            int u = head[v];
            if (in[v] - k >= in[u]) return rev[in[v] - k];
            k -= in[v] - in[u] + 1;
            v = par[u];
        }
    }

    int lca(int u, int v) {
        for (;; v = par[head[v]]) {
            if (in[u] > in[v]) swap(u, v);
            if (head[u] == head[v]) return u;
        }
    }

    template<typename T, typename Q, typename F>
    T query(int u, int v, const T &e, const Q &q, const F &f, bool edge = false) {
        T l = e, r = e;
        for (;; v = par[head[v]]) {
            if (in[u] > in[v]) swap(u, v), swap(l, r);
            if (head[u] == head[v]) break;
            l = f(q(in[head[v]], in[v] + 1), l);
        }
        return f(f(q(in[u] + edge, in[v] + 1), l), r);
    }

    int dist(int u, int v) { return d[u] + d[v] - 2 * d[lca(u, v)]; }

    int jump(int s, int t, int i) {
        if (!i) return s;
        int l = lca(s, t);
        int dst = d[s] + d[t] - d[l] * 2;
        if (dst < i) return -1;
        if (d[s] - d[l] >= i) return la(s, i);
        i -= d[s] - d[l];
        return la(t, d[t] - d[l] - i);
    }
};

template<typename T>
struct edge {
    int to;
    T cost;

    edge(int to, T cost) : to(to), cost(cost) {}

    edge &operator=(const int &x) {
        to = x;
        return *this;
    }

    operator int() const { return to; }
};

int main() {
    cin.tie(0), cout.tie(0);
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    vector<vector<edge<ll>>> g(n);
    rep(i, 1, n) {
        int x, c;
        cin >> x >> c;
        x--;
        g[x].emplace_back(i, c);
    }
    HLD hld(g);
    hld.build();

    ll sum = 0;
    int now = 0;
    cout << sum << "\n";

    vector<map<int, int>> G(n);
    set<int> s;
    s.emplace(0);

    vl par(n);

    auto connect = [&](int i, int j) {
        if(i == j) return;
        if (hld.d[i] < hld.d[j]) swap(i, j);
        par[i] = j;
        G[i][hld.jump(i, j, 1)] = j;
        G[j][hld.jump(j, i, 1)] = i;
    };

    vl d(n), dp(n);
    auto dfs = [&](auto &&f, int x) -> void {
        fore(e, g[x]) {
            d[e] = d[x] + e.cost;
            dp[e] = e.cost;
            f(f, e);
        }
    };
    dfs(dfs, 0);
//    cout << d << endl;
    auto dist = [&](int i, int j) {
        int u = hld.lca(i, j);
//        cout << "lca: " << i << " " << j << " " << u << endl;
        return d[i] + d[j] - d[u] * 2;
    };

    auto f = [](int x, int y) { return x + y; };
    segtree<int, decltype(f)> seg(n, f, 0);
    seg.update(0, 1);

    rep(i, 1, n) {
        int idx = hld.in[i];
        auto it = s.lower_bound(idx);
        int mypar;
        if (it != begin(s)) {
            int l = hld.rev[*prev(it)];
            int c = hld.lca(l, i);
            mypar = c;
            if (s.insert(hld.in[c]).second) {
                int p = par[l];
                connect(l, c);
                connect(i, c);
                connect(c, p);
            }
        }
        if (it != end(s)) {
            int r = hld.rev[*it];
            int c = hld.lca(r, i);
            if(hld.d[mypar] < hld.d[c]) mypar = c;
            if (s.insert(hld.in[c]).second) {
                int p = par[r];
                connect(r, c);
                connect(i, c);
                connect(c, p);
            }
        }
        connect(i, mypar);
        s.insert(hld.in[i]);
        seg.update(hld.in[i], 1);
//        cout << now << " " << dist(now, i) << endl;
        sum += dist(now, i);

        int cnt = 0;
        while (true) {
            cnt++;
            if(cnt > 2) assert(0);
            if (now == i) break;
            int nxt = hld.jump(now, i, 1);
            int to = G[now][nxt];
            ll s;
            if (hld.d[nxt] > hld.d[now]) s = seg.prod(hld.in[nxt], hld.out[nxt]);
            else s = (i + 1) - seg.prod(hld.in[now], hld.out[now]);
//            cout << now << " " << nxt << " " << to << " " << s << endl;
            if (s > (i + 1 - s)) {
                sum -= dist(now, to) * (s * 2 - (i + 1));
                now = to;
            } else {
                break;
            }
        }
        cout << sum << '\n';
    }
}
accuracy: 0.35135135135135137
time_ms: 320
memory_kb: 74924
final_rank: 17

code_snippet: // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2636

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

#define call_from_test
template<typename Vertex, typename Cluster, size_t N>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  inline static array<Vertex, 2*N> pool_vertex;
  inline static size_t ptr_vertex = 0;

  inline static array<Node, 4*N> pool_node;
  inline static size_t ptr_node = 0;

  Cluster id;

  template<typename ...Args>
  inline Vertex* create(Args ...args){
    auto t=&pool_vertex[ptr_vertex++];
    auto dummy=&pool_vertex[ptr_vertex++];
    *t=Vertex(forward<Args>(args)...);
    link(t,id,dummy);
    return t;
  }

  Node* recycle=nullptr;
  inline void dispose_node(Node* t){
    t->p=recycle;
    recycle=t;
  }

  inline Node* get_new_node(){
    if(recycle) return new(exchange(recycle,recycle->p)) Node;
    return &(pool_node[ptr_node++]);
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=get_new_node();
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=get_new_node();
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=get_new_node();
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose(u);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose(v);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      dispose_node(ll->p);
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      dispose_node(rk);
      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    assert(nnv);
    Node* vv=expose(nnv);
    propagate(vv);
    if(vv->vs[1]==v) set_toggle(vv);
    if(vv->vs[0]==v){
      Node* nv=compress(ee,vv);
      ee->p=nv;
      pushup(ee);
      vv->p=nv;
      pushup(vv);pushup(nv);
      ll=nv;
    }else{
      Node* nv=vv;
      Node* ch=nv->ch[0];
      propagate(ch);
      nv->ch[0]=ee;
      ee->p=nv;
      pushup(ee);

      Node* bt=nv->q;
      Node* rk=nullptr;
      if(bt){
        propagate(bt);
        rk=rake(bt,ch);
        bt->p=rk;
        ch->p=rk;
        pushup(bt);pushup(ch);
      }else{
        rk=ch;
      }
      nv->q=rk;
      rk->p=nv;
      pushup(rk);pushup(nv);
      ll=nv;
    }

    assert(nnu);
    Node* uu=expose(nnu);
    propagate(uu);
    if(uu->vs[0]==u) set_toggle(uu);
    if(uu->vs[1]==u){
      Node* tp=compress(uu,ll);
      uu->p=tp;
      ll->p=tp;
      pushup(uu);pushup(ll);pushup(tp);
    }else{
      Node* nu=uu;
      Node* ch=nu->ch[1];
      toggle(ch);
      propagate(ch);

      nu->ch[1]=ll;
      ll->p=nu;
      pushup(ll);

      Node* al=nu->q;
      Node* rk=nullptr;
      if(al){
        propagate(al);
        rk=rake(al,ch);
        al->p=rk;
        ch->p=rk;
        pushup(al);pushup(ch);
      }else{
        rk=ch;
      }
      nu->q=rk;
      rk->p=nu;
      pushup(rk);pushup(nu);
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    assert(rr->ch[1]->type==Type::Edge);
    dispose_node(rr->ch[1]);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat);
    }
    return res;
  }
};


struct Vertex{
  void* handle;
  // 0: dead, 1: alive
  int color;
  Vertex(int color=0):handle(nullptr),color(color){}
};

template<typename T>
struct DistanceSum{
  struct pi{
    T cnt;
    Vertex* ptr;
    pi():cnt(-1),ptr(nullptr){}
    pi(T cnt,Vertex* ptr):cnt(cnt),ptr(ptr){}
    bool operator<(const pi &o)const{return cnt<o.cnt;}
  };

  T len,cnt,chd,ans;
  T sum_l,sum_r;
  pi md;

  DistanceSum(T len=0):len(len),cnt(0),chd(0),ans(0),sum_l(0),sum_r(0){}

  void toggle(){swap(sum_l,sum_r);}

  static DistanceSum compress(
    const DistanceSum& x,Vertex *v,const DistanceSum& y){
    DistanceSum nxt;
    nxt.len=x.len+y.len;
    nxt.cnt=x.cnt+x.chd+(v->color)+y.cnt;
    nxt.chd=0;
    assert(y.chd==0);

    nxt.ans=x.sum_l+y.sum_r;

    nxt.sum_l+=x.sum_l;
    nxt.sum_l+=y.sum_l;
    nxt.sum_l+=(x.cnt+x.chd+(v->color))*y.len;

    nxt.sum_r+=x.sum_r;
    nxt.sum_r+=y.sum_r;
    nxt.sum_r+=(x.chd+(v->color)+y.cnt)*x.len;

    nxt.md=pi(nxt.cnt,v);

    return nxt;
  }

  static DistanceSum rake(const DistanceSum& x,const DistanceSum& y){
    DistanceSum nxt;
    nxt.len=x.len;
    nxt.cnt=x.cnt;
    nxt.chd=x.chd+y.cnt+y.chd;

    nxt.ans=x.sum_l+y.sum_l;

    nxt.sum_l+=x.sum_l;
    nxt.sum_l+=y.sum_l;

    nxt.sum_r+=x.sum_r;
    nxt.sum_r+=y.sum_l;

    nxt.md=max(x.md,y.md);

    return nxt;
  }
};

template<typename T, size_t N>
Vertex* centroid(TopTree<Vertex, DistanceSum<T>, N> &G, Vertex* v){
  using TT = typename remove_reference<decltype(G)>::type;
  using Node = typename TT::Node;
  using Type = typename TT::Type;

  Node* rt=G.expose(v);
  if(rt->type==Type::Edge) return v;

  Node* cc=rt;
  Vertex* ctr=nullptr;

  T lv=0,rv=0,sum=rt->dat.cnt;
  while(cc->type==Type::Compress){
    G.propagate(cc);

    Node* ll=cc->ch[0];
    if((ll->dat.cnt+lv)*2>sum){
      assert(ll->type!=Type::Edge);
      rv+=cc->dat.md.cnt-ll->dat.cnt;
      cc=ll;
      continue;
    }

    Node* rr=cc->ch[1];
    if((rr->dat.cnt+rv)*2>sum){
      assert(rr->type!=Type::Edge);
      lv+=cc->dat.md.cnt-rr->dat.cnt;
      cc=rr;
      continue;
    }

    Node* mm=cc->q;
    if(mm and mm->dat.md.cnt*2>sum){
      assert(mm->type!=Type::Edge);
      rv+=lv;lv=0;
      rv+=cc->dat.md.cnt-mm->dat.md.cnt;
      cc=(decltype(cc))mm->dat.md.ptr->handle;
      continue;
    }

    ctr=cc->dat.md.ptr;
    break;
  }
  return ctr;
}


#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  int n;
  cin>>n;

  using ll = long long;
  const size_t N = 2e5;
  using Cluster = DistanceSum<ll>;
  TopTree<Vertex, Cluster, N> G;

  vector<Vertex*> vs(n);
  for(int i=0;i<n;i++) vs[i]=G.create(0);

  for(int i=1;i<n;i++){
    int p,d;
    cin>>p>>d;
    p--;
    G.link(vs[p],d,vs[i]);
  }

  for(int i=0;i<n;i++){
    G.set_vertex(vs[i],1);
    cout<<G.get_subtree(centroid(G,vs[i])).ans<<newl;
  }
  return 0;
}
accuracy: 1
time_ms: 610
memory_kb: 107888
final_rank: 8

code_snippet: // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2636

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

#define call_from_test
template<typename Vertex, typename Cluster, size_t N>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  inline static array<Vertex, 2*N> pool_vertex;
  inline static size_t ptr_vertex = 0;

  inline static array<Node, 4*N> pool_node;
  inline static size_t ptr_node = 0;

  Cluster id;

  inline Vertex* create(Vertex v=Vertex()){
    auto t=&pool_vertex[ptr_vertex++];
    auto dummy=&pool_vertex[ptr_vertex++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  Node* recycle=nullptr;
  inline void dispose_node(Node* t){
    t->p=recycle;
    recycle=t;
  }

  inline Node* get_new_node(){
    if(recycle) return new(exchange(recycle,recycle->p)) Node;
    return &(pool_node[ptr_node++]);
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=get_new_node();
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=get_new_node();
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=get_new_node();
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose(u);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose(v);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      dispose_node(ll->p);
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    assert(nnv);
    Node* vv=expose(nnv);
    propagate(vv);
    if(vv->vs[1]==v) set_toggle(vv);
    if(vv->vs[0]==v){
      Node* nv=compress(ee,vv);
      ee->p=nv;
      pushup(ee);
      vv->p=nv;
      pushup(vv);pushup(nv);
      ll=nv;
    }else{
      Node* nv=vv;
      Node* ch=nv->ch[0];
      propagate(ch);
      nv->ch[0]=ee;
      ee->p=nv;
      pushup(ee);

      Node* bt=nv->q;
      Node* rk=nullptr;
      if(bt){
        propagate(bt);
        rk=rake(bt,ch);
        bt->p=rk;
        ch->p=rk;
        pushup(bt);pushup(ch);
      }else{
        rk=ch;
      }
      nv->q=rk;
      rk->p=nv;
      pushup(rk);pushup(nv);
      ll=nv;
    }

    assert(nnu);
    Node* uu=expose(nnu);
    propagate(uu);
    if(uu->vs[0]==u) set_toggle(uu);
    if(uu->vs[1]==u){
      Node* tp=compress(uu,ll);
      uu->p=tp;
      ll->p=tp;
      pushup(uu);pushup(ll);pushup(tp);
    }else{
      Node* nu=uu;
      Node* ch=nu->ch[1];
      toggle(ch);
      propagate(ch);

      nu->ch[1]=ll;
      ll->p=nu;
      pushup(ll);

      Node* al=nu->q;
      Node* rk=nullptr;
      if(al){
        propagate(al);
        rk=rake(al,ch);
        al->p=rk;
        ch->p=rk;
        pushup(al);pushup(ch);
      }else{
        rk=ch;
      }
      nu->q=rk;
      rk->p=nu;
      pushup(rk);pushup(nu);
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    dispose_node(rr->ch[1]);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat);
    }
    return res;
  }
};


template<typename T, size_t LIM>
struct DistanceSum{
  struct Vertex{
    void* handle;
    T color;
    Vertex(T color=0):handle(nullptr),color(color){}
  };

  struct Cluster{
    struct pi{
      T cnt;
      Vertex* ptr;
      pi():cnt(-1),ptr(nullptr){}
      pi(T cnt,Vertex* ptr):cnt(cnt),ptr(ptr){}
      bool operator<(const pi &o)const{return cnt<o.cnt;}
    };

    T len,cnt,chd,ans;
    T sum_l,sum_r;
    pi md;

    Cluster(T len=0):len(len),cnt(0),chd(0),ans(0),sum_l(0),sum_r(0){}

    void toggle(){swap(sum_l,sum_r);}

    static Cluster compress(Cluster x,Vertex *v,Cluster y){
      Cluster nxt;
      nxt.len=x.len+y.len;
      nxt.cnt=x.cnt+x.chd+(v->color)+y.cnt;
      nxt.chd=0;
      assert(y.chd==0);

      nxt.ans=x.sum_l+y.sum_r;

      nxt.sum_l+=x.sum_l;
      nxt.sum_l+=y.sum_l;
      nxt.sum_l+=(x.cnt+x.chd+(v->color))*y.len;

      nxt.sum_r+=x.sum_r;
      nxt.sum_r+=y.sum_r;
      nxt.sum_r+=(x.chd+(v->color)+y.cnt)*x.len;

      nxt.md=pi(nxt.cnt,v);

      return nxt;
    }

    static Cluster rake(Cluster x,Cluster y){
      Cluster nxt;
      nxt.len=x.len;
      nxt.cnt=x.cnt;
      nxt.chd=x.chd+y.cnt+y.chd;

      nxt.ans=x.sum_l+y.sum_l;

      nxt.sum_l+=x.sum_l;
      nxt.sum_l+=y.sum_l;

      nxt.sum_r+=x.sum_r;
      nxt.sum_r+=y.sum_l;

      nxt.md=max(x.md,y.md);

      return nxt;
    }
  };

  TopTree<Vertex, Cluster, LIM> G;
  using Type = typename decltype(G)::Type;

  Vertex* centroid(Vertex* v){
    auto rt=G.expose(v);
    if(rt->type==Type::Edge) return v;

    auto cc=rt;
    Vertex* ctr=nullptr;

    T lv=0,rv=0,sum=rt->dat.cnt;
    while(cc->type==Type::Compress){
      G.propagate(cc);

      auto ll=cc->ch[0];
      if((ll->dat.cnt+lv)*2>sum){
        assert(ll->type!=Type::Edge);
        rv+=cc->dat.md.cnt-ll->dat.cnt;
        cc=ll;
        continue;
      }

      auto rr=cc->ch[1];
      if((rr->dat.cnt+rv)*2>sum){
        assert(rr->type!=Type::Edge);
        lv+=cc->dat.md.cnt-rr->dat.cnt;
        cc=rr;
        continue;
      }

      auto mm=cc->q;
      if(mm and mm->dat.md.cnt*2>sum){
        assert(mm->type!=Type::Edge);
        rv+=lv;lv=0;
        rv+=cc->dat.md.cnt-mm->dat.md.cnt;
        cc=(decltype(cc))mm->dat.md.ptr->handle;
        continue;
      }

      ctr=cc->dat.md.ptr;
      break;
    }
    return ctr;
  }
  Vertex* create(T color){return G.create(Vertex(color));}
  void link(Vertex* u,Cluster w,Vertex* v){G.link(u,Cluster(w),v);}
  void cut(Vertex* u,Vertex* v){G.cut(u,v);}
  void set_vertex(Vertex* u,T color){G.set_vertex(u,Vertex(color));}
  T query(Vertex* v){return G.get_subtree(v).ans;}
};

#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  int n;
  cin>>n;

  using ll = long long;
  const size_t LIM = 2e5;
  DistanceSum<ll, LIM> G;

  vector<decltype(G)::Vertex*> vs(n);
  for(int i=0;i<n;i++) vs[i]=G.create(0);

  for(int i=1;i<n;i++){
    int p,d;
    cin>>p>>d;
    p--;
    G.link(vs[p],d,vs[i]);
  }

  for(int i=0;i<n;i++){
    G.set_vertex(vs[i],1);
    cout<<G.query(G.centroid(vs[i]))<<newl;
  }
  return 0;
}
accuracy: 1
time_ms: 660
memory_kb: 107896
final_rank: 9

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2636"

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

#define call_from_test

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename Vertex, typename Cluster, size_t LIM>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  static array<Vertex, LIM> pool_v;
  static array<Node, LIM> pool_c;
  size_t ptr_v,ptr_c;

  Cluster id;
  TopTree(Cluster id=Cluster()):ptr_v(0),ptr_c(0),id(id){}

  inline Vertex* create(Vertex v=Vertex()){
    auto t=&pool_v[ptr_v++];
    auto dummy=&pool_v[ptr_v++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=&(pool_c[ptr_c++]);
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose(u);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose(v);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    if(!nnv) ll=ee;
    else{
      Node* vv=expose(nnv);
      propagate(vv);
      if(vv->vs[1]==v) set_toggle(vv);
      if(vv->vs[0]==v){
        Node* nv=compress(ee,vv);
        ee->p=nv;
        pushup(ee);
        vv->p=nv;
        pushup(vv);pushup(nv);
        ll=nv;
      }else{
        Node* nv=vv;
        Node* ch=nv->ch[0];
        propagate(ch);
        nv->ch[0]=ee;
        ee->p=nv;
        pushup(ee);

        Node* bt=nv->q;
        Node* rk=nullptr;
        if(bt){
          propagate(bt);
          rk=rake(bt,ch);
          bt->p=rk;
          ch->p=rk;
          pushup(bt);pushup(ch);
        }else{
          rk=ch;
        }
        nv->q=rk;
        rk->p=nv;
        pushup(rk);pushup(nv);
        ll=nv;
      }
    }

    if(nnu){
      Node* uu=expose(nnu);
      propagate(uu);
      if(uu->vs[0]==u) set_toggle(uu);
      if(uu->vs[1]==u){
        Node* tp=compress(uu,ll);
        uu->p=tp;
        ll->p=tp;
        pushup(uu);pushup(ll);pushup(tp);
      }else{
        Node* nu=uu;
        Node* ch=nu->ch[1];
        toggle(ch);
        propagate(ch);

        nu->ch[1]=ll;
        ll->p=nu;
        pushup(ll);

        Node* al=nu->q;
        Node* rk=nullptr;
        if(al){
          propagate(al);
          rk=rake(al,ch);
          al->p=rk;
          ch->p=rk;
          pushup(al);pushup(ch);
        }else{
          rk=ch;
        }
        nu->q=rk;
        rk->p=nu;
        pushup(rk);pushup(nu);
      }
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat);
    }
    return res;
  }
};
template<typename Vertex, typename Cluster, size_t LIM>
array<Vertex, LIM> TopTree<Vertex, Cluster, LIM>::pool_v;
template<typename Vertex, typename Cluster, size_t LIM>
array<typename TopTree<Vertex, Cluster, LIM>::Node, LIM>
TopTree<Vertex, Cluster, LIM>::pool_c;
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "toptree.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE

template<typename T, size_t LIM>
struct DistanceSum{
  struct Vertex{
    void* handle;
    T color;
    Vertex(T color=0):handle(nullptr),color(color){}
  };

  struct Cluster{
    struct pi{
      T cnt;
      Vertex* ptr;
      pi():cnt(-1),ptr(nullptr){}
      pi(T cnt,Vertex* ptr):cnt(cnt),ptr(ptr){}
      bool operator<(const pi &o)const{return cnt<o.cnt;}
    };

    T len,cnt,chd,ans;
    T sum_l,sum_r;
    pi md;

    Cluster(T len=0):len(len),cnt(0),chd(0),ans(0),sum_l(0),sum_r(0){}

    void toggle(){swap(sum_l,sum_r);}

    static Cluster compress(Cluster x,Vertex *v,Cluster y){
      Cluster nxt;
      nxt.len=x.len+y.len;
      nxt.cnt=x.cnt+x.chd+(v->color)+y.cnt;
      nxt.chd=0;
      assert(y.chd==0);

      nxt.ans=x.sum_l+y.sum_r;

      nxt.sum_l+=x.sum_l;
      nxt.sum_l+=y.sum_l;
      nxt.sum_l+=(x.cnt+x.chd+(v->color))*y.len;

      nxt.sum_r+=x.sum_r;
      nxt.sum_r+=y.sum_r;
      nxt.sum_r+=(x.chd+(v->color)+y.cnt)*x.len;

      nxt.md=pi(nxt.cnt,v);

      return nxt;
    }

    static Cluster rake(Cluster x,Cluster y){
      Cluster nxt;
      nxt.len=x.len;
      nxt.cnt=x.cnt;
      nxt.chd=x.chd+y.cnt+y.chd;

      nxt.ans=x.sum_l+y.sum_l;

      nxt.sum_l+=x.sum_l;
      nxt.sum_l+=y.sum_l;

      nxt.sum_r+=x.sum_r;
      nxt.sum_r+=y.sum_l;

      nxt.md=max(x.md,y.md);

      return nxt;
    }
  };

  TopTree<Vertex, Cluster, LIM> G;
  using Type = typename decltype(G)::Type;

  Vertex* centroid(Vertex* v){
    auto rt=G.expose(v);
    if(rt->type==Type::Edge) return v;

    auto cc=rt;
    Vertex* ctr=nullptr;

    T lv=0,rv=0,sum=rt->dat.cnt;
    while(cc->type==Type::Compress){
      G.propagate(cc);

      auto ll=cc->ch[0];
      if((ll->dat.cnt+lv)*2>sum){
        assert(ll->type!=Type::Edge);
        rv+=cc->dat.md.cnt-ll->dat.cnt;
        cc=ll;
        continue;
      }

      auto rr=cc->ch[1];
      if((rr->dat.cnt+rv)*2>sum){
        assert(rr->type!=Type::Edge);
        lv+=cc->dat.md.cnt-rr->dat.cnt;
        cc=rr;
        continue;
      }

      auto mm=cc->q;
      if(mm and mm->dat.md.cnt*2>sum){
        assert(mm->type!=Type::Edge);
        rv+=lv;lv=0;
        rv+=cc->dat.md.cnt-mm->dat.md.cnt;
        cc=(decltype(cc))mm->dat.md.ptr->handle;
        continue;
      }

      ctr=cc->dat.md.ptr;
      break;
    }
    return ctr;
  }
  Vertex* create(T color){return G.create(Vertex(color));}
  void link(Vertex* u,Cluster w,Vertex* v){G.link(u,Cluster(w),v);}
  void cut(Vertex* u,Vertex* v){G.cut(u,v);}
  void set_vertex(Vertex* u,T color){G.set_vertex(u,Vertex(color));}
  T query(Vertex* v){return G.get_subtree(v).ans;}
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  int n;
  cin>>n;

  using ll = long long;
  const size_t LIM = 1e6;
  DistanceSum<ll, LIM> G;

  vector<decltype(G)::Vertex*> vs(n);
  for(int i=0;i<n;i++) vs[i]=G.create(0);

  for(int i=1;i<n;i++){
    int p,d;
    cin>>p>>d;
    p--;
    G.link(vs[p],d,vs[i]);
  }

  for(int i=0;i<n;i++){
    G.set_vertex(vs[i],1);
    cout<<G.query(G.centroid(vs[i]))<<newl;
  }
  return 0;
}
accuracy: 1
time_ms: 1010
memory_kb: 139336
final_rank: 13

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, H, W, L, R;
long long int N, M, K, H, W, L, R;

class Lowest_Common_Ancestor {
	vector<int>depth;
	vector<vector<int>>edge;
	int height = 0;
	int node;
public:
	vector<vector<int>>parent;
	Lowest_Common_Ancestor(int num) {
		num++;
		node = num;
		while (num) {
			height++;
			num /= 2;
		}
		parent.resize(height);
		edge.resize(node);
		depth.resize(node);
		for (int i = 0; i < height; i++)parent[i].resize(node);
	}
	void Add_Edge(int a, int b) {
		edge[a].push_back(b);
		edge[b].push_back(a);
		return;
	}
	void Update(int rtnode) {
		queue<int>QQ;
		for (int i = 0; i < node; i++) depth[i] = INT_MAX;
		depth[rtnode] = 0;
		QQ.push(rtnode);
		while (!QQ.empty()) {
			int c = QQ.front();
			for (auto i : edge[c]) {
				if (depth[i] > depth[c] + 1) {
					depth[i] = depth[c] + 1;
					QQ.push(i);
				}
			}
			QQ.pop();
		}
		parent[0][rtnode] = -1;
		for (int i = 0; i < node; i++) {
			for (auto j : edge[i]) {
				if (depth[i] - 1 == depth[j]) {
					parent[0][i] = j;
					break;
				}
			}
		}
		for (int i = 0; i < height - 1; i++) {
			for (int j = 0; j < node; j++) {
				if (parent[i][j] < 0)parent[i + 1][j] = -1;
				else parent[i + 1][j] = parent[i][parent[i][j]];
			}
		}
		return;
	}
	int LCA(int u, int v) {
		if (depth[u] > depth[v])swap(u, v);
		for (int i = 0; i < height; i++) {
			if ((depth[v] - depth[u]) >> i & 1) {
				v = parent[i][v];
			}
		}
		if (u == v)return u;
		for (int i = height - 1; i >= 0; i--) {
			if (parent[i][v] != parent[i][u]) {
				u = parent[i][u];
				v = parent[i][v];
			}
		}
		return parent[0][u];
	}
	int Dist(int u, int v) {
		return depth[u] + depth[v] - depth[LCA(u, v)] * 2;
	}
};

class Add_Segment_Tree {
	vector<long long int>v;
	long long int ret;
	int num;
	long long int Update(int place) {
		if (place >= v.size() / 2) {
			return v[place];
		}
		v[place] = Update(place * 2) + Update(place * 2 + 1);
		return v[place];
	}
public:
	Add_Segment_Tree(int n) {
		n++;
		num = 1;
		while (num < n * 2)num *= 2;
		v.resize(num, 0);
	}
	void Add(int place, long long int num, bool update) {
		place += v.size() / 2;
		v[place] += num;
		if (!update)return;
		place /= 2;
		while (place) {
			v[place] = v[place * 2] + v[place * 2 + 1];
			place /= 2;
		}
	}
	void TopDown() {
		Update(1);
	}
	long long int Sum(int a, int b) {
		ret = 0;
		b++;
		for (a += num / 2, b += num / 2; a < b; a >>= 1, b >>= 1) {
			if (a & 1)ret += v[a++];
			if (b & 1)ret += v[--b];
		}
		return ret;
	}
};


class EulerTour {	//	0-indexed
public:
	vector<int>tour;
	vector<int>depth;
	vector<int>l;
	vector<int>r;
private:
	int node;
	vector<vector<int>>edge;
	int root = 0;
	void DFS(int n) {
		tour.push_back(n);
		for (auto i : edge[n]) {
			if (depth[n] < depth[i]) {
				DFS(i);
			}
		}
		tour.push_back(n);
		return;
	}
	void BFS() {
		for (auto &i : depth)i = MOD;
		depth[root] = 0;
		queue<int>Q;
		Q.push(root);
		while (!Q.empty()) {
			int cn = Q.front();
			int c = depth[cn];
			Q.pop();
			for (auto i : edge[cn]) {
				if (depth[i] > c + 1) {
					depth[i] = c + 1;
					Q.push(i);
				}
			}
		}
		return;
	}
public:
	EulerTour(int n, int ro) {
		node = n;
		node++;
		root = ro;
		edge.resize(node);
		depth.resize(node, MOD);
		l.resize(node, MOD);
		r.resize(node, 0);
		return;
	}
	void Add_Edge(int a, int b) {
		edge[a].push_back(b);
		edge[b].push_back(a);
		return;
	}
	void Retour() {
		if (!tour.empty())tour.clear();
		BFS();
		DFS(root);
		for (int i = 0; i < tour.size(); i++) {
			l[tour[i]] = min(l[tour[i]], i);
			r[tour[i]] = max(r[tour[i]], i);
		}
		return;
	}
};

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

	cin >> N;
	vector<vector<pair<int, int>>>edge(N);
	Lowest_Common_Ancestor lca(N);
	EulerTour et(N, 0);
	for (int i = 1; i < N; i++) {
		cin >> L >> R;
		L--;
		edge[L].push_back({ i,R });
		edge[i].push_back({ L,R });
		lca.Add_Edge(i, L);
		et.Add_Edge(i, L);
	}
	lca.Update(0);
	et.Retour();
	Add_Segment_Tree asg(et.tour.size());
	vector<long long int>depth(N, MOD*MOD);
	vector<int>step(N, MOD);
	step[0] = 0;
	depth[0] = 0;
	queue<int>Q;
	Q.push(0);
	while (!Q.empty()) {
		int cn = Q.front();
		Q.pop();
		for (auto i : edge[cn]) {
			if (depth[i.first] > depth[cn] + i.second) {
				depth[i.first] = depth[cn] + i.second;
				step[i.first] = step[cn] + 1;
				Q.push(i.first);
			}
		}
	}
	long long int ans = 0;
	long long int p = 0;
	cout << ans << endl;
	asg.Add(et.l[0], 1, true);
	for (int i = 1; i < N; i++) {
		asg.Add(et.l[i], 1, true);
		int l = lca.LCA(p, i);
		ans -= depth[l] * 2;
		ans += depth[p];
		ans += depth[i];
		//cout << ans << endl;
		auto  sump = asg.Sum(et.l[p], et.r[p]);
		if (i == p) {

		}
		else if (l == p) {//今いる場所の下に追加
			int nx = i;
			int dis = step[i] - step[p] - 1;
			for (int j = lca.parent.size() - 1; j >= 0; j--) {
				if (dis >= (1 << j) && asg.Sum(et.l[lca.parent[j][nx]], et.r[lca.parent[j][nx]]) * 2 <= i) {
					nx = lca.parent[j][nx];
					dis -= 1 << j;
				}
			}
			if (asg.Sum(et.l[nx], et.r[nx]) * 2 <= i)nx = lca.parent[0][nx];
			ans -= (depth[p] - depth[nx])*(i + 1 - asg.Sum(et.l[nx], et.r[nx]) * 2);
			p = nx;
		}
		else {//それ以外
			int nx = p;
			int dis = step[p] - step[l] - 1;
			for (int j = lca.parent.size() - 1; j >= 0; j--) {
		//		cout << dis << endl;
				if (dis >= (1 << j) && asg.Sum(et.l[lca.parent[j][nx]], et.r[lca.parent[j][nx]]) * 2 <= i) {
					nx = lca.parent[j][nx];
					dis -= 1 << j;
				}
			}
			//cout << "fst " << nx << " " << asg.Sum(et.l[nx], et.r[nx]) << endl;
			if (asg.Sum(et.l[nx], et.r[nx]) * 2 <= i)nx = lca.parent[0][nx];
			//cout <<"snd "<< nx <<" "<< asg.Sum(et.l[nx], et.r[nx]) << endl;
			if (nx != l) {//lcaを跨がない
				ans += (depth[nx] - depth[p])*(i + 1 - sump * 2);
				p = nx;
			}
			else {//lcaを跨ぐ
				int dis = step[i] - step[l] - 1;
				if (dis > 0) {
				//	cout << "dis " << dis << endl;
					nx = i;
				//	cout << "nx " << nx << endl;
					for (int j = lca.parent.size() - 1; j >= 0; j--) {
						if (dis >= (1 << j) && asg.Sum(et.l[lca.parent[j][nx]], et.r[lca.parent[j][nx]]) * 2 <= i) {
							nx = lca.parent[j][nx];
							dis -= 1 << j;
						}
					}
				//	cout << "nxsnd " << nx << endl;
				}
				if (asg.Sum(et.l[nx], et.r[nx]) * 2 <= i)nx = lca.parent[0][nx];
				ans += (depth[l] * 2 - depth[nx] - depth[p])*(i + 1 - sump * 2);
				p = nx;
			}
		}
		//cout << ans << " " << p << endl;
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 750
memory_kb: 68992
final_rank: 5

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, H, W, L, R;
long long int N, M, K, H, W, L, R;

class Lowest_Common_Ancestor {
	vector<int>depth;
	vector<vector<int>>edge;
	int height = 0;
	int node;
public:
	vector<vector<int>>parent;
	Lowest_Common_Ancestor(int num) {
		num++;
		node = num;
		while (num) {
			height++;
			num /= 2;
		}
		parent.resize(height);
		edge.resize(node);
		depth.resize(node);
		for (int i = 0; i < height; i++)parent[i].resize(node);
	}
	void Add_Edge(int a, int b) {
		edge[a].push_back(b);
		edge[b].push_back(a);
		return;
	}
	void Update(int rtnode) {
		queue<int>QQ;
		for (int i = 0; i < node; i++) depth[i] = INT_MAX;
		depth[rtnode] = 0;
		QQ.push(rtnode);
		while (!QQ.empty()) {
			int c = QQ.front();
			for (auto i : edge[c]) {
				if (depth[i] > depth[c] + 1) {
					depth[i] = depth[c] + 1;
					QQ.push(i);
				}
			}
			QQ.pop();
		}
		parent[0][rtnode] = -1;
		for (int i = 0; i < node; i++) {
			for (auto j : edge[i]) {
				if (depth[i] - 1 == depth[j]) {
					parent[0][i] = j;
					break;
				}
			}
		}
		for (int i = 0; i < height - 1; i++) {
			for (int j = 0; j < node; j++) {
				if (parent[i][j] < 0)parent[i + 1][j] = -1;
				else parent[i + 1][j] = parent[i][parent[i][j]];
			}
		}
		return;
	}
	int LCA(int u, int v) {
		if (depth[u] > depth[v])swap(u, v);
		for (int i = 0; i < height; i++) {
			if ((depth[v] - depth[u]) >> i & 1) {
				v = parent[i][v];
			}
		}
		if (u == v)return u;
		for (int i = height - 1; i >= 0; i--) {
			if (parent[i][v] != parent[i][u]) {
				u = parent[i][u];
				v = parent[i][v];
			}
		}
		return parent[0][u];
	}
	int Dist(int u, int v) {
		return depth[u] + depth[v] - depth[LCA(u, v)] * 2;
	}
};

class Add_Segment_Tree {
	vector<long long int>v;
	long long int ret;
	int num;
	long long int Update(int place) {
		if (place >= v.size() / 2) {
			return v[place];
		}
		v[place] = Update(place * 2) + Update(place * 2 + 1);
		return v[place];
	}
public:
	Add_Segment_Tree(int n) {
		n++;
		num = 1;
		while (num < n * 2)num *= 2;
		v.resize(num, 0);
	}
	void Add(int place, long long int num, bool update) {
		place += v.size() / 2;
		v[place] += num;
		if (!update)return;
		place /= 2;
		while (place) {
			v[place] = v[place * 2] + v[place * 2 + 1];
			place /= 2;
		}
	}
	void TopDown() {
		Update(1);
	}
	long long int Sum(int a, int b) {
		ret = 0;
		b++;
		for (a += num / 2, b += num / 2; a < b; a >>= 1, b >>= 1) {
			if (a & 1)ret += v[a++];
			if (b & 1)ret += v[--b];
		}
		return ret;
	}
};


class EulerTour {	//	0-indexed
public:
	vector<int>tour;
	vector<int>depth;
	vector<int>l;
	vector<int>r;
private:
	int node;
	vector<vector<int>>edge;
	int root = 0;
	void DFS(int n) {
		tour.push_back(n);
		for (auto i : edge[n]) {
			if (depth[n] < depth[i]) {
				DFS(i);
			}
		}
		tour.push_back(n);
		return;
	}
	void BFS() {
		for (auto &i : depth)i = MOD;
		depth[root] = 0;
		queue<int>Q;
		Q.push(root);
		while (!Q.empty()) {
			int cn = Q.front();
			int c = depth[cn];
			Q.pop();
			for (auto i : edge[cn]) {
				if (depth[i] > c + 1) {
					depth[i] = c + 1;
					Q.push(i);
				}
			}
		}
		return;
	}
public:
	EulerTour(int n, int ro) {
		node = n;
		node++;
		root = ro;
		edge.resize(node);
		depth.resize(node, MOD);
		l.resize(node, MOD);
		r.resize(node, 0);
		return;
	}
	void Add_Edge(int a, int b) {
		edge[a].push_back(b);
		edge[b].push_back(a);
		return;
	}
	void Retour() {
		if (!tour.empty())tour.clear();
		BFS();
		DFS(root);
		for (int i = 0; i < tour.size(); i++) {
			l[tour[i]] = min(l[tour[i]], i);
			r[tour[i]] = max(r[tour[i]], i);
		}
		return;
	}
};

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

	cin >> N;
	vector<vector<pair<int, int>>>edge(N);
	Lowest_Common_Ancestor lca(N);
	EulerTour et(N, 0);
	for (int i = 1; i < N; i++) {
		cin >> L >> R;
		L--;
		edge[L].push_back({ i,R });
		edge[i].push_back({ L,R });
		lca.Add_Edge(i, L);
		et.Add_Edge(i, L);
	}
	lca.Update(0);
	et.Retour();
	Add_Segment_Tree asg(et.tour.size());
	vector<long long int>depth(N, MOD*MOD);
	vector<int>step(N, MOD);
	step[0] = 0;
	depth[0] = 0;
	queue<int>Q;
	Q.push(0);
	while (!Q.empty()) {
		int cn = Q.front();
		Q.pop();
		for (auto i : edge[cn]) {
			if (depth[i.first] > depth[cn] + i.second) {
				depth[i.first] = depth[cn] + i.second;
				step[i.first] = step[cn] + 1;
				Q.push(i.first);
			}
		}
	}
	long long int ans = 0;
	long long int p = 0;
	cout << ans << endl;
	asg.Add(et.l[0], 1, true);
	for (int i = 1; i < N; i++) {
		asg.Add(et.l[i], 1, true);
		int l = lca.LCA(p, i);
		ans -= depth[l] * 2;
		ans += depth[p];
		ans += depth[i];
		auto  sump = asg.Sum(et.l[p], et.r[p]);
		//cout << sump << endl;
		if (sump * 2 <= i) {//上に移動
			int nx = p;
			int dis = step[l] - step[p] - 1;
			for (int j = lca.parent.size() - 1; j >= 0; j--) {
				if (dis >= 1 << j && asg.Sum(et.l[lca.parent[j][nx]], et.r[lca.parent[j][nx]] == sump)) {
					nx = lca.parent[j][nx];
					dis -= 1 << j;
				}
			}
			nx = lca.parent[0][nx];
			if (nx != l) {//lcaを跨がない
				ans += (depth[nx] - depth[p])*(i + 1 - sump * 2);
				p = nx;
			}
			else if (l <= i || asg.Sum(et.l[l], et.r[l]) <= i) {//lcaで止まる
				ans += (depth[nx] - depth[p])*(i + 1 - sump * 2);
				p = nx;
			}
			else {//lcaを跨ぐ
				int dis = step[i] - step[l] - 1;
				nx = i;
				for (int j = lca.parent.size() - 1; j >= 0; j--) {
					if (dis<=1<<j&&asg.Sum(et.l[lca.parent[j][nx]], et.r[lca.parent[j][nx]]) * 2 <= i) {
						nx = lca.parent[j][nx];
						dis -= 1 << j;
					}
				}
				nx = lca.parent[0][nx];
				ans += (depth[l] * 2 - depth[i] - depth[p])*(i + 1 - sump * 2);
				p = nx;
			}
		}
		else {
			if (i != p && sump * 2 > i + 3) {
			//	cout << "JO "<<i << endl;
				int nx = i;
				int dis = step[i] - step[p] - 1;
				for (int j = lca.parent.size() - 1; j >= 0; j--) {
					if (dis >= 1 << j && asg.Sum(et.l[lca.parent[j][nx]], et.r[lca.parent[j][nx]]) * 2 <= i) {
						nx = lca.parent[j][nx];
						dis -= 1 << j;
					}
				}
			//	cout <<"nx "<< nx << endl;
				if(asg.Sum(et.l[nx], et.r[nx]) * 2 <= i)nx = lca.parent[0][nx];
				ans -= (depth[p] - depth[nx])*(i + 1 - asg.Sum(et.l[nx], et.r[nx]) * 2);
				p = nx;
			}
		}
		cout << ans << endl;
	}
}
accuracy: 0.2702702702702703
time_ms: 490
memory_kb: 66568
final_rank: 20

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
template<class T>
void dmp(T a){
	rep(i,a.size()) cout << a[i] << " ";
	cout << endl;
}
template<class T>
bool chmax(T&a, T b){
	if(a < b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a, T b){
	if(a > b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 1000000007;//998244353
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}

struct dat {
	int cnt1;
	ll sum, sum1, sum2;
	//reverseする
	void rv(){
		swap(sum1, sum2);
	}
};

struct node{
	node *l, *r, *p;
	int id, rev;
	dat D, L, S;
	priority_queue<P>ins, del;
	
	node(int i, int c, int w) : l(0), r(0), p(0), id(i), rev(0){
		D = S = {c, w, w, w};
		L = {0, 0, 0, 0};
	}
};

inline bool is_root(node *n){
	return n -> p == NULL || n -> p -> l != n && n -> p -> r != n;
}

inline bool left(node *n){
	return n == n -> p -> l;
}

//遅延評価
//push(n)を走らせた後にはn->l と n->r の値は正しく計算されている必要あり
inline void push(node *n){
	if(n->rev){
		swap(n->l, n->r);
		if(n->l){
			n->l->rev ^= 1;
			n->l->D.rv();
		}
		if(n->r){
			n->r->rev ^= 1;
			n->r->D.rv();
		}
		n->rev = 0;
	}
}

//値の再計算
inline void update(node *n){
	//最初に遅延評価
	push(n);
	
	n->D.cnt1 = (n->l?n->l->D.cnt1:0) + (n->r?n->r->D.cnt1:0) + n->L.cnt1 + n->S.cnt1;
	n->D.sum = (n->l?n->l->D.sum:0) + (n->r?n->r->D.sum:0) + n->S.sum;
	n->D.sum1 = 0;
	if(n->l) n->D.sum1 += n->l->D.sum1;
	if(n->r) n->D.sum1 += n->r->D.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->r->D.cnt1;
	if(n->S.cnt1) n->D.sum1 += 1LL*(n->S.sum+(n->l?n->l->D.sum:0));
	n->D.sum1 += n->L.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->L.cnt1;
	
	n->D.sum2 = 0;
	if(n->l) n->D.sum2 += n->l->D.sum2 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->l->D.cnt1;
	if(n->r) n->D.sum2 += n->r->D.sum2;
	if(n->S.cnt1) n->D.sum2 += 1LL*(n->S.sum+(n->r?n->r->D.sum:0));
	n->D.sum2 += n->L.sum1 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->L.cnt1;
}
inline void connect(node *n, node *p, bool l){
	(l ? p -> l : p -> r) = n;
	if(n) n -> p = p;
}
//rotateが呼ばれる前には関与しているノードの遅延評価をする必要がある
inline void rotate(node *n){
	node *p = n -> p, *g = p -> p;
	bool l = left(n);
	connect(l ? n -> r : n -> l, p, l);
	bool ex = 0;
	if(!is_root(p)) connect(n, g, left(p));
	else{
		//light edgeを繋ぎ変える
		if(g){
			g->del.push(mp(p->D.cnt1, p->id));
			g->ins.push(mp(p->D.cnt1, n->id));
		}
		n -> p = g;
	}
	connect(p, n, !l);
	update(p), update(n);
}
inline void splay(node *n){
    if(is_root(n)){
        update(n);
        return;
    }
	while(!is_root(n)){
		node *p = n -> p, *g = p -> p;
		//関与する頂点群の遅延評価をする
		if(!is_root(p)) push(g);
		push(p), push(n);
		if(!is_root(p)) rotate(left(n) ^ left(p) ? n : p);
		rotate(n);
	}
}
//返り値はnじゃないよ
//部分木クエリの時は適切に更新
inline node* expose(node *n){
	node *last = NULL;
	for(node *m = n; m; m = m -> p){
		splay(m);
		if(m->r) {
			m->L.cnt1 += m->r->D.cnt1;
			m->L.sum1 += m->r->D.sum1;
			m->L.sum2 += m->r->D.sum1;
			m->ins.push(mp(m->r->D.cnt1, m->r->id));
		}
		m -> r = last;
		if(m->r) {
			m->L.cnt1 -= m->r->D.cnt1;
			m->L.sum1 -= m->r->D.sum1;
			m->L.sum2 -= m->r->D.sum1;
			m->del.push(mp(m->r->D.cnt1, m->r->id));
 		}
		update(m);
		last = m;
	}
	splay(n);
	return last;
}
//部分木クエリの時は適切に更新
inline void link(node *m, node *n){
	expose(m), expose(n);
	m -> p = n;
	n->L.cnt1 += m->D.cnt1;
	n->L.sum1 += m->D.sum1;
	n->L.sum2 += m->D.sum1;
	n->ins.push(mp(m->D.cnt1, m->id));
	update(n);
}
inline node* find_root(node *n){
	if(!n) return (node*)NULL;
	while(1){
		push(n);
		if(n->r) n = n->r;
		else break;
	}
	return n;
}
inline node* cut(node *n){
	expose(n);
	node *ret = n->l;
	n -> l -> p = NULL;
	n -> l = NULL;
	update(n);
	return find_root(ret);
}
//nを根に持っていく
//updateは必要ない
inline void evert(node *n){
	expose(n);
	n->rev ^= 1;
	n->D.rv();
}
const int MAXN = 400005;
node *V[MAXN];

int find(node *n, int sz){
	int lim = (sz+1)/2;
	while(1){
		push(n);
		if(n->r && n->r->D.cnt1 >= lim) n = n->r;
		else if(n->l && n->D.cnt1 - n->l->D.cnt1 < lim){
		    lim -= (n->D.cnt1-n->l->D.cnt1); n = n->l; 
		}
		else{
			while(n->del.size() && n->ins.size() && n->del.top() == n->ins.top()){
				n->del.pop();
				n->ins.pop();
			}
			if(n->ins.size() && n->ins.top().fi >= (sz+1)/2){
				lim = (sz+1)/2; n = V[n->ins.top().sc];
			}
			else return n->id;
		}
	}
}
int n, q;
ll sum;
int nxt = 200001;
int main(){
	scanf("%d",&n);
	repn(i, n) V[i] = new node(i, 0, 0);
	repn(i,n-1){
		int a,c; scanf("%d%d",&a,&c);
		V[nxt] = new node(nxt, 0, c);
		link(V[i+1], V[nxt]);
		link(V[nxt], V[a]);
		nxt++;
	}
	for(int k=1;k<=n;k++){
		evert(V[k]);
		V[k]->S.cnt1 ^= 1;
		update(V[k]);
		int c = find(V[k], V[k]->D.cnt1);
		evert(V[c]);
		printf("%lld\n", V[c]->D.sum1);
	}
}
accuracy: 1
time_ms: 830
memory_kb: 155700
final_rank: 15

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
template<class T>
void dmp(T a){
	rep(i,a.size()) cout << a[i] << " ";
	cout << endl;
}
template<class T>
bool chmax(T&a, T b){
	if(a < b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a, T b){
	if(a > b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 1000000007;//998244353
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}

struct dat {
	int cnt1;
	ll sum, sum1, sum2;
	//reverseする
	void rv(){
		swap(sum1, sum2);
	}
};

struct node{
	node *l, *r, *p;
	int id, rev;
	dat D, L, S;
	multiset<P, greater<P>>L_sz;
	
	node(int i, int c, int w) : l(0), r(0), p(0), id(i), rev(0){
		D = S = {c, w, w, w};
		L = {0, 0, 0, 0};
		L_sz.clear();
	}
};

inline bool is_root(node *n){
	return n -> p == NULL || n -> p -> l != n && n -> p -> r != n;
}

inline bool left(node *n){
	return n == n -> p -> l;
}

//遅延評価
//push(n)を走らせた後にはn->l と n->r の値は正しく計算されている必要あり
inline void push(node *n){
	if(n->rev){
		swap(n->l, n->r);
		if(n->l){
			n->l->rev ^= 1;
			n->l->D.rv();
		}
		if(n->r){
			n->r->rev ^= 1;
			n->r->D.rv();
		}
		n->rev = 0;
	}
}

//値の再計算
inline void update(node *n){
	//最初に遅延評価
	push(n);
	
	n->D.cnt1 = (n->l?n->l->D.cnt1:0) + (n->r?n->r->D.cnt1:0) + n->L.cnt1 + n->S.cnt1;
	n->D.sum = (n->l?n->l->D.sum:0) + (n->r?n->r->D.sum:0) + n->S.sum;
	n->D.sum1 = 0;
	if(n->l) n->D.sum1 += n->l->D.sum1;
	if(n->r) n->D.sum1 += n->r->D.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->r->D.cnt1;
	if(n->S.cnt1) n->D.sum1 += 1LL*(n->S.sum+(n->l?n->l->D.sum:0));
	n->D.sum1 += n->L.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->L.cnt1;
	
	n->D.sum2 = 0;
	if(n->l) n->D.sum2 += n->l->D.sum2 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->l->D.cnt1;
	if(n->r) n->D.sum2 += n->r->D.sum2;
	if(n->S.cnt1) n->D.sum2 += 1LL*(n->S.sum+(n->r?n->r->D.sum:0));
	n->D.sum2 += n->L.sum1 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->L.cnt1;
}
inline void connect(node *n, node *p, bool l){
	(l ? p -> l : p -> r) = n;
	if(n) n -> p = p;
}
//rotateが呼ばれる前には関与しているノードの遅延評価をする必要がある
inline void rotate(node *n){
	node *p = n -> p, *g = p -> p;
	bool l = left(n);
	connect(l ? n -> r : n -> l, p, l);
	bool ex = 0;
	if(!is_root(p)) connect(n, g, left(p));
	else{
		//light edgeを繋ぎ変える
		if(g){
			g->L_sz.erase(mp(p->D.cnt1, p->id));
			g->L_sz.insert(mp(p->D.cnt1, n->id));
		}
		n -> p = g;
	}
	connect(p, n, !l);
	update(p), update(n);
}
inline void splay(node *n){
    if(is_root(n)){
        update(n);
        return;
    }
	while(!is_root(n)){
		node *p = n -> p, *g = p -> p;
		//関与する頂点群の遅延評価をする
		if(!is_root(p)) push(g);
		push(p), push(n);
		if(!is_root(p)) rotate(left(n) ^ left(p) ? n : p);
		rotate(n);
	}
}
//返り値はnじゃないよ
//部分木クエリの時は適切に更新
inline node* expose(node *n){
	node *last = NULL;
	for(node *m = n; m; m = m -> p){
		splay(m);
		if(m->r) {
			m->L.cnt1 += m->r->D.cnt1;
			m->L.sum1 += m->r->D.sum1;
			m->L.sum2 += m->r->D.sum1;
			m->L_sz.insert(mp(m->r->D.cnt1, m->r->id));
		}
		m -> r = last;
		if(m->r) {
			m->L.cnt1 -= m->r->D.cnt1;
			m->L.sum1 -= m->r->D.sum1;
			m->L.sum2 -= m->r->D.sum1;
			m->L_sz.erase(mp(m->r->D.cnt1, m->r->id));
 		}
		update(m);
		last = m;
	}
	splay(n);
	return last;
}
//部分木クエリの時は適切に更新
inline void link(node *m, node *n){
	expose(m), expose(n);
	m -> p = n;
	n->L.cnt1 += m->D.cnt1;
	n->L.sum1 += m->D.sum1;
	n->L.sum2 += m->D.sum1;
	n->L_sz.insert(mp(m->D.cnt1, m->id));
	update(n);
}
inline node* find_root(node *n){
	if(!n) return (node*)NULL;
	while(1){
		push(n);
		if(n->r) n = n->r;
		else break;
	}
	return n;
}
inline node* cut(node *n){
	expose(n);
	node *ret = n->l;
	n -> l -> p = NULL;
	n -> l = NULL;
	update(n);
	return find_root(ret);
}
//nを根に持っていく
//updateは必要ない
inline void evert(node *n){
	expose(n);
	n->rev ^= 1;
	n->D.rv();
}
const int MAXN = 400005;
node *V[MAXN];

int find(node *n, int sz){
	int lim = (sz+1)/2;
	while(1){
		push(n);
		if(n->r && n->r->D.cnt1 >= lim) n = n->r;
		else if(n->l && n->D.cnt1 - n->l->D.cnt1 < lim){
		    lim -= (n->D.cnt1-n->l->D.cnt1); n = n->l; 
		}
		else if(n->L_sz.size() && (*n->L_sz.begin()).fi >= (sz+1)/2){
			lim = (sz+1)/2; n = V[(*n->L_sz.begin()).sc];
		}
		else return n->id;
	}
}
int n, q;
ll sum;
int nxt = 200001;
int main(){
	scanf("%d",&n);
	repn(i, n) V[i] = new node(i, 0, 0);
	repn(i,n-1){
		int a,c; scanf("%d%d",&a,&c);
		V[nxt] = new node(nxt, 0, c);
		link(V[i+1], V[nxt]);
		link(V[nxt], V[a]);
		nxt++;
	}
	for(int k=1;k<=n;k++){
		evert(V[k]);
		V[k]->S.cnt1 ^= 1;
		update(V[k]);
		int c = find(V[k], V[k]->D.cnt1);
		evert(V[c]);
		printf("%lld\n", V[c]->D.sum1);
	}
}
accuracy: 1
time_ms: 770
memory_kb: 100120
final_rank: 11

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
template<class T>
void dmp(T a){
	rep(i,a.size()) cout << a[i] << " ";
	cout << endl;
}
template<class T>
bool chmax(T&a, T b){
	if(a < b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a, T b){
	if(a > b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 1000000007;//998244353
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}

struct dat {
	int cnt1;
	ll sum, sum1, sum2;
	//reverseする
	void rv(){
		swap(sum1, sum2);
	}
};

struct node{
	node *l, *r, *p;
	int id, rev;
	dat D, L, S;
	multiset<P, greater<P>>L_sz;
	
	node(int i, int c, int w) : l(0), r(0), p(0), id(i), rev(0){
		D = S = {c, w, w, w};
		L = {0, 0, 0, 0};
		L_sz.clear();
	}
};

inline bool is_root(node *n){
	return n -> p == NULL || n -> p -> l != n && n -> p -> r != n;
}

inline bool left(node *n){
	return n == n -> p -> l;
}

//遅延評価
//push(n)を走らせた後にはn->l と n->r の値は正しく計算されている必要あり
inline void push(node *n){
	if(n->rev){
		swap(n->l, n->r);
		if(n->l){
			n->l->rev ^= 1;
			n->l->D.rv();
		}
		if(n->r){
			n->r->rev ^= 1;
			n->r->D.rv();
		}
		n->rev = 0;
	}
}

//値の再計算
inline void update(node *n){
	//最初に遅延評価
	push(n);
	
	n->D.cnt1 = (n->l?n->l->D.cnt1:0) + (n->r?n->r->D.cnt1:0) + n->L.cnt1 + n->S.cnt1;
	n->D.sum = (n->l?n->l->D.sum:0) + (n->r?n->r->D.sum:0) + n->S.sum;
	n->D.sum1 = 0;
	if(n->l) n->D.sum1 += n->l->D.sum1;
	if(n->r) n->D.sum1 += n->r->D.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->r->D.cnt1;
	if(n->S.cnt1) n->D.sum1 += 1LL*(n->S.sum+(n->l?n->l->D.sum:0));
	n->D.sum1 += n->L.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->L.cnt1;
	
	n->D.sum2 = 0;
	if(n->l) n->D.sum2 += n->l->D.sum2 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->l->D.cnt1;
	if(n->r) n->D.sum2 += n->r->D.sum2;
	if(n->S.cnt1) n->D.sum2 += 1LL*(n->S.sum+(n->r?n->r->D.sum:0));
	n->D.sum2 += n->L.sum1 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->L.cnt1;
}
inline void connect(node *n, node *p, bool l){
	(l ? p -> l : p -> r) = n;
	if(n) n -> p = p;
}
//rotateが呼ばれる前には関与しているノードの遅延評価をする必要がある
inline void rotate(node *n){
	node *p = n -> p, *g = p -> p;
	bool l = left(n);
	connect(l ? n -> r : n -> l, p, l);
	bool ex = 0;
	if(!is_root(p)) connect(n, g, left(p));
	else{
		//light edgeを繋ぎ変える
		if(g){
			g->L_sz.erase(mp(p->D.cnt1, p->id));
			g->L_sz.erase(mp(p->D.cnt1, n->id));
		}
		n -> p = g;
	}
	connect(p, n, !l);
	update(p), update(n);
}
inline void splay(node *n){
    if(is_root(n)){
        update(n);
        return;
    }
	while(!is_root(n)){
		node *p = n -> p, *g = p -> p;
		//関与する頂点群の遅延評価をする
		if(!is_root(p)) push(g);
		push(p), push(n);
		if(!is_root(p)) rotate(left(n) ^ left(p) ? n : p);
		rotate(n);
	}
}
//返り値はnじゃないよ
//部分木クエリの時は適切に更新
inline node* expose(node *n){
	node *last = NULL;
	for(node *m = n; m; m = m -> p){
		splay(m);
		if(m->r) {
			m->L.cnt1 += m->r->D.cnt1;
			m->L.sum1 += m->r->D.sum1;
			m->L.sum2 += m->r->D.sum1;
			m->L_sz.insert(mp(m->r->D.cnt1, m->r->id));
		}
		m -> r = last;
		if(m->r) {
			m->L.cnt1 -= m->r->D.cnt1;
			m->L.sum1 -= m->r->D.sum1;
			m->L.sum2 -= m->r->D.sum1;
			m->L_sz.erase(mp(m->r->D.cnt1, m->r->id));
 		}
		update(m);
		last = m;
	}
	splay(n);
	return last;
}
//部分木クエリの時は適切に更新
inline void link(node *m, node *n){
	expose(m), expose(n);
	m -> p = n;
	n->L.cnt1 += m->D.cnt1;
	n->L.sum1 += m->D.sum1;
	n->L.sum2 += m->D.sum1;
	n->L_sz.insert(mp(m->D.cnt1, m->id));
	update(n);
}
inline node* find_root(node *n){
	if(!n) return (node*)NULL;
	while(1){
		push(n);
		if(n->r) n = n->r;
		else break;
	}
	return n;
}
inline node* cut(node *n){
	expose(n);
	node *ret = n->l;
	n -> l -> p = NULL;
	n -> l = NULL;
	update(n);
	return find_root(ret);
}
//nを根に持っていく
//updateは必要ない
inline void evert(node *n){
	expose(n);
	n->rev ^= 1;
	n->D.rv();
}
const int MAXN = 400005;
node *V[MAXN];

int find(node *n, int sz){
	int lim = (sz+1)/2;
	while(1){
		push(n);
		if(n->r && n->r->D.cnt1 >= lim) n = n->r;
		else if(n->l && n->D.cnt1 - n->l->D.cnt1 < lim){
		    lim -= (n->D.cnt1-n->l->D.cnt1); n = n->l; 
		}
		else if(n->L_sz.size() && (*n->L_sz.begin()).fi >= (sz+1)/2){
			lim = (sz+1)/2; n = V[(*n->L_sz.begin()).sc];
		}
		else return n->id;
	}
}
int n, q;
ll sum;
int nxt = 200001;
int main(){
	scanf("%d",&n);
	repn(i, n) V[i] = new node(i, 0, 0);
	repn(i,n-1){
		int a,c; scanf("%d%d",&a,&c);
		V[nxt] = new node(nxt, 0, c);
		link(V[i+1], V[nxt]);
		link(V[nxt], V[a]);
		nxt++;
	}
	for(int k=1;k<=n;k++){
		evert(V[k]);
		V[k]->S.cnt1 ^= 1;
		update(V[k]);
		int c = find(V[k], V[k]->D.cnt1);
		evert(V[c]);
		printf("%lld\n", V[c]->D.sum1);
	}
}
accuracy: 1
time_ms: 690
memory_kb: 100084
final_rank: 7

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
template<class T>
void dmp(T a){
	rep(i,a.size()) cout << a[i] << " ";
	cout << endl;
}
template<class T>
bool chmax(T&a, T b){
	if(a < b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a, T b){
	if(a > b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 1000000007;//998244353
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}

//verified: yosupo judge (x3), AOJ 2450, Hackerrank white falcon, IJPC2012-3A

struct dat {
	int cnt1;
	ll sum, sum1, sum2;
	//reverseする
	void rv(){
		swap(sum1, sum2);
	}
};

struct node{
	node *l, *r, *p;
	int id, rev;
	dat D, L, S;
	multiset<P, greater<P>>L_sz;
	
	node(int i, int c, int w) : l(0), r(0), p(0), id(i), rev(0){
		D = S = {c, w, w, w};
		L = {0, 0, 0, 0};
		L_sz.clear();
	}
};

inline bool is_root(node *n){
	return n -> p == NULL || n -> p -> l != n && n -> p -> r != n;
}

inline bool left(node *n){
	return n == n -> p -> l;
}

//遅延評価
//push(n)を走らせた後にはn->l と n->r の値は正しく計算されている必要あり
inline void push(node *n){
	if(n->rev){
		swap(n->l, n->r);
		if(n->l){
			n->l->rev ^= 1;
			n->l->D.rv();
		}
		if(n->r){
			n->r->rev ^= 1;
			n->r->D.rv();
		}
		n->rev = 0;
	}
}

//値の再計算
inline void update(node *n){
	//最初に遅延評価
	push(n);
	
	n->D.cnt1 = (n->l?n->l->D.cnt1:0) + (n->r?n->r->D.cnt1:0) + n->L.cnt1 + n->S.cnt1;
	n->D.sum = (n->l?n->l->D.sum:0) + (n->r?n->r->D.sum:0) + n->S.sum;
	n->D.sum1 = 0;
	if(n->l) n->D.sum1 += n->l->D.sum1;
	if(n->r) n->D.sum1 += n->r->D.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->r->D.cnt1;
	if(n->S.cnt1) n->D.sum1 += 1LL*(n->S.sum+(n->l?n->l->D.sum:0));
	n->D.sum1 += n->L.sum1 + 1LL*(n->S.sum+(n->l?n->l->D.sum:0)) * n->L.cnt1;
	
	n->D.sum2 = 0;
	if(n->l) n->D.sum2 += n->l->D.sum2 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->l->D.cnt1;
	if(n->r) n->D.sum2 += n->r->D.sum2;
	if(n->S.cnt1) n->D.sum2 += 1LL*(n->S.sum+(n->r?n->r->D.sum:0));
	n->D.sum2 += n->L.sum1 + 1LL*(n->S.sum+(n->r?n->r->D.sum:0)) * n->L.cnt1;
}
inline void connect(node *n, node *p, bool l){
	(l ? p -> l : p -> r) = n;
	if(n) n -> p = p;
}
//rotateが呼ばれる前には関与しているノードの遅延評価をする必要がある
inline void rotate(node *n){
	node *p = n -> p, *g = p -> p;
	bool l = left(n);
	connect(l ? n -> r : n -> l, p, l);
	bool ex = 0;
	if(!is_root(p)) connect(n, g, left(p));
	else{
		//light edgeを繋ぎ変える
		if(g) g->L_sz.erase(mp(p->D.cnt1, p->id));
		n -> p = g;
		if(g) ex = 1;
	}
	connect(p, n, !l);
	update(p), update(n);
	if(ex) g->L_sz.insert(mp(n->D.cnt1, n->id));
}
inline void splay(node *n){
    if(is_root(n)){
        update(n);
        return;
    }
	while(!is_root(n)){
		node *p = n -> p, *g = p -> p;
		//関与する頂点群の遅延評価をする
		if(!is_root(p)) push(g);
		push(p), push(n);
		if(!is_root(p)) rotate(left(n) ^ left(p) ? n : p);
		rotate(n);
	}
}
//返り値はnじゃないよ
inline node* expose(node *n){
	node *last = NULL;
	for(node *m = n; m; m = m -> p){
		splay(m);
		if(m->r) {
			m->L.cnt1 += m->r->D.cnt1;
			m->L.sum1 += m->r->D.sum1;
			m->L.sum2 += m->r->D.sum1;
			m->L_sz.insert(mp(m->r->D.cnt1, m->r->id));
		}
		m -> r = last;
		if(m->r) {
			m->L.cnt1 -= m->r->D.cnt1;
			m->L.sum1 -= m->r->D.sum1;
			m->L.sum2 -= m->r->D.sum1;
			m->L_sz.erase(mp(m->r->D.cnt1, m->r->id));
 		}
		update(m);
		last = m;
	}
	splay(n);
	return last;
}
inline void link(node *m, node *n){
	expose(m), expose(n);
	m -> p = n;
	n->L.cnt1 += m->D.cnt1;
	n->L.sum1 += m->D.sum1;
	n->L.sum2 += m->D.sum1;
	n->L_sz.insert(mp(m->D.cnt1, m->id));
	update(n);
}
inline node* find_root(node *n){
	if(!n) return (node*)NULL;
	while(1){
		push(n);
		if(n->r) n = n->r;
		else break;
	}
	return n;
}
inline node* cut(node *n){
	expose(n);
	node *ret = n->l;
	n -> l -> p = NULL;
	n -> l = NULL;
	update(n);
	return find_root(ret);
}
//nを根に持っていく
//updateは必要ない
inline void evert(node *n){
	expose(n);
	n->rev ^= 1;
	n->D.rv();
}
const int MAXN = 400005;
node *V[MAXN];

int find(node *n, int sz){
	int lim = (sz+1)/2;
	while(1){
		push(n);
		if(n->r && n->r->D.cnt1 >= lim) n = n->r;
		else if(n->l && n->D.cnt1 - n->l->D.cnt1 < lim){
		    lim -= (n->D.cnt1-n->l->D.cnt1); n = n->l; 
		}
		else if(n->L_sz.size() && (*n->L_sz.begin()).fi >= (sz+1)/2){
			lim = (sz+1)/2; n = V[(*n->L_sz.begin()).sc];
		}
		else return n->id;
	}
}
int n, q;
ll sum;
int nxt = 200001;
int main(){
	scanf("%d",&n);
	repn(i, n) V[i] = new node(i, 0, 0);
	repn(i,n-1){
		int a,c; scanf("%d%d",&a,&c);
		V[nxt] = new node(nxt, 0, c);
		link(V[i+1], V[nxt]);
		link(V[nxt], V[a]);
		nxt++;
	}
	for(int k=1;k<=n;k++){
		evert(V[k]);
		V[k]->S.cnt1 ^= 1;
		update(V[k]);
		int c = find(V[k], V[k]->D.cnt1);
		evert(V[c]);
		printf("%lld\n", V[c]->D.sum1);
	}
}
accuracy: 1
time_ms: 770
memory_kb: 100084
final_rank: 10

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2636"

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

#define call_from_test

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename Vertex, typename Cluster, size_t LIM>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  static array<Vertex, LIM> pool_v;
  static array<Node, LIM> pool_c;
  size_t ptr_v,ptr_c;

  Cluster id;
  TopTree(Cluster id=Cluster()):ptr_v(0),ptr_c(0),id(id){}

  inline Vertex* create(Vertex v=Vertex()){
    auto t=&pool_v[ptr_v++];
    auto dummy=&pool_v[ptr_v++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=&(pool_c[ptr_c++]);
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat,t->q->vs[0]);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat,r->vs[0]);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose(u);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose(v);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    if(!nnv) ll=ee;
    else{
      Node* vv=expose(nnv);
      propagate(vv);
      if(vv->vs[1]==v) set_toggle(vv);
      if(vv->vs[0]==v){
        Node* nv=compress(ee,vv);
        ee->p=nv;
        pushup(ee);
        vv->p=nv;
        pushup(vv);pushup(nv);
        ll=nv;
      }else{
        Node* nv=vv;
        Node* ch=nv->ch[0];
        propagate(ch);
        nv->ch[0]=ee;
        ee->p=nv;
        pushup(ee);

        Node* bt=nv->q;
        Node* rk=nullptr;
        if(bt){
          propagate(bt);
          rk=rake(bt,ch);
          bt->p=rk;
          ch->p=rk;
          pushup(bt);pushup(ch);
        }else{
          rk=ch;
        }
        nv->q=rk;
        rk->p=nv;
        pushup(rk);pushup(nv);
        ll=nv;
      }
    }

    if(nnu){
      Node* uu=expose(nnu);
      propagate(uu);
      if(uu->vs[0]==u) set_toggle(uu);
      if(uu->vs[1]==u){
        Node* tp=compress(uu,ll);
        uu->p=tp;
        ll->p=tp;
        pushup(uu);pushup(ll);pushup(tp);
      }else{
        Node* nu=uu;
        Node* ch=nu->ch[1];
        toggle(ch);
        propagate(ch);

        nu->ch[1]=ll;
        ll->p=nu;
        pushup(ll);

        Node* al=nu->q;
        Node* rk=nullptr;
        if(al){
          propagate(al);
          rk=rake(al,ch);
          al->p=rk;
          ch->p=rk;
          pushup(al);pushup(ch);
        }else{
          rk=ch;
        }
        nu->q=rk;
        rk->p=nu;
        pushup(rk);pushup(nu);
      }
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat,rk->vs[0]);
    }
    return res;
  }
};
template<typename Vertex, typename Cluster, size_t LIM>
array<Vertex, LIM> TopTree<Vertex, Cluster, LIM>::pool_v;
template<typename Vertex, typename Cluster, size_t LIM>
array<typename TopTree<Vertex, Cluster, LIM>::Node, LIM>
TopTree<Vertex, Cluster, LIM>::pool_c;
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "toptree.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE

template<typename T, size_t LIM>
struct DistanceSum{
  struct Vertex{
    void* handle;
    T color;
    Vertex(T color=0):handle(nullptr),color(color){}
  };

  struct Cluster{
    struct pi{
      T cnt;
      Vertex* ptr;
      pi():cnt(-1),ptr(nullptr){}
      pi(T cnt,Vertex* ptr):cnt(cnt),ptr(ptr){}
      bool operator<(const pi &o)const{return cnt<o.cnt;}
    };

    T len,cnt,chd,ans;
    T sum_l,sum_r;
    pi md;

    Cluster(T len=0):len(len),cnt(0),chd(0),ans(0),sum_l(0),sum_r(0){}

    void toggle(){swap(sum_l,sum_r);}

    static Cluster compress(Cluster x,Vertex *v,Cluster y){
      Cluster nxt;
      nxt.len=x.len+y.len;
      nxt.cnt=x.cnt+x.chd+(v->color)+y.cnt;
      nxt.chd=0;
      assert(y.chd==0);

      nxt.ans=x.sum_l+y.sum_r;

      nxt.sum_l+=x.sum_l;
      nxt.sum_l+=y.sum_l;
      nxt.sum_l+=(x.cnt+x.chd+(v->color))*y.len;

      nxt.sum_r+=x.sum_r;
      nxt.sum_r+=y.sum_r;
      nxt.sum_r+=(x.chd+(v->color)+y.cnt)*x.len;

      nxt.md=pi(nxt.cnt,v);

      return nxt;
    }

    static Cluster rake(Cluster x,Cluster y,Vertex *v){
      assert((v->color)==0);
      Cluster nxt;
      nxt.len=x.len;
      nxt.cnt=x.cnt;
      nxt.chd=x.chd+y.cnt+y.chd;

      nxt.ans=x.sum_l+y.sum_l;

      nxt.sum_l+=x.sum_l;
      nxt.sum_l+=y.sum_l;

      nxt.sum_r+=x.sum_r;
      nxt.sum_r+=y.sum_l;

      nxt.md=max(x.md,y.md);

      return nxt;
    }
  };

  TopTree<Vertex, Cluster, LIM> G;
  using Type = typename decltype(G)::Type;

  Vertex* centroid(Vertex* v){
    auto rt=G.expose(v);
    if(rt->type==Type::Edge) return v;

    auto cc=rt;
    Vertex* ctr=nullptr;

    T lv=0,rv=0,sum=rt->dat.cnt;
    while(cc->type==Type::Compress){
      G.propagate(cc);

      auto ll=cc->ch[0];
      if((ll->dat.cnt+lv)*2>sum){
        assert(ll->type!=Type::Edge);
        rv+=cc->dat.md.cnt-ll->dat.cnt;
        cc=ll;
        continue;
      }

      auto rr=cc->ch[1];
      if((rr->dat.cnt+rv)*2>sum){
        assert(rr->type!=Type::Edge);
        lv+=cc->dat.md.cnt-rr->dat.cnt;
        cc=rr;
        continue;
      }

      auto mm=cc->q;
      if(mm and mm->dat.md.cnt*2>sum){
        assert(mm->type!=Type::Edge);
        rv+=lv;lv=0;
        rv+=cc->dat.md.cnt-mm->dat.md.cnt;
        cc=(decltype(cc))mm->dat.md.ptr->handle;
        continue;
      }

      ctr=cc->dat.md.ptr;
      break;
    }
    return ctr;
  }

  T query(Vertex* v){return G.get_subtree(v).ans;}
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  int n;
  cin>>n;

  using ll = long long;
  const size_t LIM = 1e6;
  DistanceSum<ll, LIM> G;
  using Vertex = decltype(G)::Vertex;
  using Cluster = decltype(G)::Cluster;

  vector<Vertex*> vs(n);
  for(int i=0;i<n;i++) vs[i]=G.G.create(Vertex(0));

  for(int i=1;i<n;i++){
    int p,d;
    cin>>p>>d;
    p--;
    G.G.link(vs[p],Cluster(d),vs[i]);
  }

  for(int i=0;i<n;i++){
    G.G.set_vertex(vs[i],Vertex(1));
    cout<<G.query(G.centroid(vs[i]))<<newl;
  }
  return 0;
}
accuracy: 1
time_ms: 1020
memory_kb: 139392
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
using Int = long long;
const char newl = '\n';

template<typename Vertex, typename Cluster, size_t LIM>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  static array<Vertex, LIM> pool_v;
  static array<Node, LIM> pool_c;
  size_t ptr_v,ptr_c;

  Cluster id;
  TopTree(Cluster id=Cluster()):ptr_v(0),ptr_c(0),id(id){}

  inline Vertex* create(Vertex v=Vertex()){
    auto t=&pool_v[ptr_v++];
    auto dummy=&pool_v[ptr_v++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=&(pool_c[ptr_c++]);
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat,t->q->vs[0]);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat,r->vs[0]);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose((Node*)u->handle);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose((Node*)v->handle);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    if(!nnv) ll=ee;
    else{
      Node* vv=expose(nnv);
      propagate(vv);
      if(vv->vs[1]==v) set_toggle(vv);
      if(vv->vs[0]==v){
        Node* nv=compress(ee,vv);
        ee->p=nv;
        pushup(ee);
        vv->p=nv;
        pushup(vv);pushup(nv);
        ll=nv;
      }else{
        Node* nv=vv;
        Node* ch=nv->ch[0];
        propagate(ch);
        nv->ch[0]=ee;
        ee->p=nv;
        pushup(ee);

        Node* bt=nv->q;
        Node* rk=nullptr;
        if(bt){
          propagate(bt);
          rk=rake(bt,ch);
          bt->p=rk;
          ch->p=rk;
          pushup(bt);pushup(ch);
        }else{
          rk=ch;
        }
        nv->q=rk;
        rk->p=nv;
        pushup(rk);pushup(nv);
        ll=nv;
      }
    }

    if(nnu){
      Node* uu=expose(nnu);
      propagate(uu);
      if(uu->vs[0]==u) set_toggle(uu);
      if(uu->vs[1]==u){
        Node* tp=compress(uu,ll);
        uu->p=tp;
        ll->p=tp;
        pushup(uu);pushup(ll);pushup(tp);
      }else{
        Node* nu=uu;
        Node* ch=nu->ch[1];
        toggle(ch);
        propagate(ch);

        nu->ch[1]=ll;
        ll->p=nu;
        pushup(ll);

        Node* al=nu->q;
        Node* rk=nullptr;
        if(al){
          propagate(al);
          rk=rake(al,ch);
          al->p=rk;
          ch->p=rk;
          pushup(al);pushup(ch);
        }else{
          rk=ch;
        }
        nu->q=rk;
        rk->p=nu;
        pushup(rk);pushup(nu);
      }
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat,rk->vs[0]);
    }
    return res;
  }
};
template<typename Vertex, typename Cluster, size_t LIM>
array<Vertex, LIM> TopTree<Vertex, Cluster, LIM>::pool_v;
template<typename Vertex, typename Cluster, size_t LIM>
array<typename TopTree<Vertex, Cluster, LIM>::Node, LIM>
TopTree<Vertex, Cluster, LIM>::pool_c;

using ll = long long;
struct Vertex{
  void* handle;
  ll color,idx;
  Vertex(ll color=0,ll idx=-1):handle(nullptr),color(color),idx(idx){}
};

struct Cluster{
  struct pi{
    ll cnt;
    Vertex* ptr;
    pi():cnt(-1),ptr(nullptr){}
    pi(ll cnt,Vertex* ptr):cnt(cnt),ptr(ptr){}
    bool operator<(const pi &o)const{return cnt<o.cnt;}
  };

  ll len,cnt,chd,ans;
  ll sum_l,sum_r;
  pi md;

  Cluster(ll len=0):len(len),cnt(0),chd(0),ans(-1),sum_l(0),sum_r(0){}

  void toggle(){swap(sum_l,sum_r);}

  static Cluster compress(Cluster x,Vertex *v,Cluster y){
    Cluster nxt;
    nxt.len=x.len+y.len;
    nxt.cnt=x.cnt+x.chd+(v->color)+y.cnt;
    nxt.chd=0;
    assert(y.chd==0);

    nxt.ans=x.sum_l+y.sum_r;
    // assert(x.sum_l+y.sum_r==x.sum_r+y.sum_l);

    nxt.sum_l+=x.sum_l;
    nxt.sum_l+=y.sum_l;
    nxt.sum_l+=(x.cnt+x.chd+(v->color))*y.len;

    nxt.sum_r+=x.sum_r;
    nxt.sum_r+=y.sum_r;
    nxt.sum_r+=(x.chd+(v->color)+y.cnt)*x.len;

    nxt.md=pi(nxt.cnt,v);

    return nxt;
  }

  static Cluster rake(Cluster x,Cluster y,Vertex *v){
    assert((v->color)==0);
    Cluster nxt;
    nxt.len=x.len;
    nxt.cnt=x.cnt;
    nxt.chd=x.chd+y.cnt+y.chd+(v->color);

    nxt.ans=x.sum_l+y.sum_l;

    nxt.sum_l+=x.sum_l;
    nxt.sum_l+=y.sum_l;
    nxt.sum_l+=(v->color)*y.len;

    nxt.sum_r+=x.sum_r;
    nxt.sum_r+=y.sum_l;
    nxt.sum_r+=(v->color)*y.len;

    nxt.md=max(x.md,y.md);

    return nxt;
  }
};


template<typename T, typename Edge>
struct ReRooting{
  struct Node{
    int to,rev;
    Edge data;
    Node(int to,Edge data):to(to),data(data){}
    bool operator<(const Node &v)const{return to<v.to;};
  };

  using F1 = function<T(T, T)>;
  using F2 = function<T(T, Edge)>;

  vector< vector<Node> > G;
  vector< vector<T> > ld,rd;
  vector<int> lp,rp;

  const F1 f1;
  const F2 f2;
  const T id;

  ReRooting(int n,const F1 f1,const F2 f2,const T id):
    G(n),ld(n),rd(n),lp(n),rp(n),f1(f1),f2(f2),id(id){}

  void add_edge(int u,int v,Edge d,Edge e){
    G[u].emplace_back(v,d);
    G[v].emplace_back(u,e);
  }

  void add_edge(int u,int v,Edge d){add_edge(u,v,d,d);}

  // k: idx for edge (not vertex)
  T dfs(int v,int k){
    while(lp[v]!=k and lp[v]<(int)G[v].size()){
      auto &e=G[v][lp[v]];
      ld[v][lp[v]+1]=f1(ld[v][lp[v]],f2(dfs(e.to,e.rev),e.data));
      lp[v]++;
    }
    while(rp[v]!=k and rp[v]>=0){
      auto &e=G[v][rp[v]];
      rd[v][rp[v]]=f1(rd[v][rp[v]+1],f2(dfs(e.to,e.rev),e.data));
      rp[v]--;
    }
    if(k<0) return rd[v][0];
    return f1(ld[v][k],rd[v][k+1]);
  }

  int search(vector<Node> &vs,int idx){
    return lower_bound(vs.begin(),vs.end(),Node(idx,vs[0].data))-vs.begin();
  }

  vector<T> build(){
    int n=G.size();
    for(int i=0;i<n;i++){
      sort(G[i].begin(),G[i].end());
      ld[i].assign((int)G[i].size()+1,id);
      rd[i].assign((int)G[i].size()+1,id);
      lp[i]=0;
      rp[i]=(int)G[i].size()-1;
    }

    for(int i=0;i<n;i++)
      for(Node &t:G[i])
        t.rev=search(G[t.to],i);

    vector<T> res;
    for(int i=0;i<n;i++)
      res.emplace_back(dfs(i,-1));

    return res;
  }

  // p: idx for vertex
  T subtree(int v,int p){
    int k=search(G[p],v);
    assert(k<(int)G[p].size() and G[p][k].to==v);
    return f2(dfs(v,G[p][k].rev),G[p][k].data);
  }
};

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  const size_t LIM = 1e6;
  TopTree<Vertex, Cluster, LIM> G;
  using Type = decltype(G)::Type;

  int n;
  cin>>n;

  vector<Vertex*> vs(n);
  for(int i=0;i<n;i++) vs[i]=G.create(Vertex(0,i+1));

  for(int i=1;i<n;i++){
    int p,d;
    cin>>p>>d;
    p--;
    G.link(vs[p],Cluster(d),vs[i]);
  }

  for(int i=0;i<n;i++){
    ll sum=i+1;

    G.set_vertex(vs[i],Vertex(1,i+1));
    auto rt=G.expose(vs[0]);
    assert(!rt->p);
    assert(rt->type==Type::Compress);
    assert(rt->dat.cnt==sum);

    auto cc=rt;
    Vertex* ctr=nullptr;

    ll lv=0,rv=0;
    while(cc->type==Type::Compress){
      G.propagate(cc);

      auto ll=cc->ch[0];
      if((ll->dat.cnt+lv)*2>sum){
        assert(ll->type!=Type::Edge);
        rv+=cc->dat.md.cnt-ll->dat.cnt;
        cc=ll;
        continue;
      }

      auto rr=cc->ch[1];
      if((rr->dat.cnt+rv)*2>sum){
        assert(rr->type!=Type::Edge);
        lv+=cc->dat.md.cnt-rr->dat.cnt;
        cc=rr;
        continue;
      }

      auto mm=cc->q;
      if(mm and mm->dat.md.cnt*2>sum){
        assert(mm->type!=Type::Edge);
        rv+=lv;lv=0;
        rv+=cc->dat.md.cnt-mm->dat.md.cnt;
        cc=(decltype(cc))mm->dat.md.ptr->handle;
        continue;
      }

      ctr=cc->dat.md.ptr;
      break;
    }

    cout<<G.get_subtree(ctr).ans<<newl;
  }

  return 0;
}
accuracy: 1
time_ms: 1110
memory_kb: 147316
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
using Int = long long;
const char newl = '\n';

template<typename Vertex, typename Cluster, size_t LIM>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  static array<Vertex, LIM> pool_v;
  static array<Node, LIM> pool_c;
  size_t ptr_v,ptr_c;

  Cluster id;
  TopTree(Cluster id=Cluster()):ptr_v(0),ptr_c(0),id(id){}

  inline Vertex* create(Vertex v=Vertex()){
    auto t=&pool_v[ptr_v++];
    auto dummy=&pool_v[ptr_v++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=&(pool_c[ptr_c++]);
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat,t->q->vs[0]);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat,r->vs[0]);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose((Node*)u->handle);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose((Node*)v->handle);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    if(!nnv) ll=ee;
    else{
      Node* vv=expose(nnv);
      propagate(vv);
      if(vv->vs[1]==v) set_toggle(vv);
      if(vv->vs[0]==v){
        Node* nv=compress(ee,vv);
        ee->p=nv;
        pushup(ee);
        vv->p=nv;
        pushup(vv);pushup(nv);
        ll=nv;
      }else{
        Node* nv=vv;
        Node* ch=nv->ch[0];
        propagate(ch);
        nv->ch[0]=ee;
        ee->p=nv;
        pushup(ee);

        Node* bt=nv->q;
        Node* rk=nullptr;
        if(bt){
          propagate(bt);
          rk=rake(bt,ch);
          bt->p=rk;
          ch->p=rk;
          pushup(bt);pushup(ch);
        }else{
          rk=ch;
        }
        nv->q=rk;
        rk->p=nv;
        pushup(rk);pushup(nv);
        ll=nv;
      }
    }

    if(nnu){
      Node* uu=expose(nnu);
      propagate(uu);
      if(uu->vs[0]==u) set_toggle(uu);
      if(uu->vs[1]==u){
        Node* tp=compress(uu,ll);
        uu->p=tp;
        ll->p=tp;
        pushup(uu);pushup(ll);pushup(tp);
      }else{
        Node* nu=uu;
        Node* ch=nu->ch[1];
        toggle(ch);
        propagate(ch);

        nu->ch[1]=ll;
        ll->p=nu;
        pushup(ll);

        Node* al=nu->q;
        Node* rk=nullptr;
        if(al){
          propagate(al);
          rk=rake(al,ch);
          al->p=rk;
          ch->p=rk;
          pushup(al);pushup(ch);
        }else{
          rk=ch;
        }
        nu->q=rk;
        rk->p=nu;
        pushup(rk);pushup(nu);
      }
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat,rk->vs[0]);
    }
    return res;
  }
};
template<typename Vertex, typename Cluster, size_t LIM>
array<Vertex, LIM> TopTree<Vertex, Cluster, LIM>::pool_v;
template<typename Vertex, typename Cluster, size_t LIM>
array<typename TopTree<Vertex, Cluster, LIM>::Node, LIM>
TopTree<Vertex, Cluster, LIM>::pool_c;

using ll = long long;
struct Vertex{
  void* handle;
  ll color,idx;
  Vertex(ll color=0,ll idx=-1):handle(nullptr),color(color),idx(idx){}
};

struct Cluster{
  struct pi{
    ll cnt;
    Vertex* ptr;
    pi():cnt(-1),ptr(nullptr){}
    pi(ll cnt,Vertex* ptr):cnt(cnt),ptr(ptr){}
    bool operator<(const pi &o)const{return cnt<o.cnt;}
  };

  ll len,cnt,chd,ans;
  ll sum_l,sum_r;
  pi md;

  Cluster(ll len=0):len(len),cnt(0),chd(0),ans(-1),sum_l(0),sum_r(0){}

  void toggle(){swap(sum_l,sum_r);}

  static Cluster compress(Cluster x,Vertex *v,Cluster y){
    Cluster nxt;
    nxt.len=x.len+y.len;
    nxt.cnt=x.cnt+x.chd+(v->color)+y.cnt;
    nxt.chd=0;
    assert(y.chd==0);

    nxt.ans=x.sum_l+y.sum_r;
    // assert(x.sum_l+y.sum_r==x.sum_r+y.sum_l);

    nxt.sum_l+=x.sum_l;
    nxt.sum_l+=y.sum_l;
    nxt.sum_l+=(x.cnt+x.chd+(v->color))*y.len;

    nxt.sum_r+=x.sum_r;
    nxt.sum_r+=y.sum_r;
    nxt.sum_r+=(x.chd+(v->color)+y.cnt)*x.len;

    nxt.md=pi(nxt.cnt,v);

    return nxt;
  }

  static Cluster rake(Cluster x,Cluster y,Vertex *v){
    assert((v->color)==0);
    Cluster nxt;
    nxt.len=x.len;
    nxt.cnt=x.cnt;
    nxt.chd=x.chd+y.cnt+y.chd+(v->color);

    nxt.ans=x.sum_l+y.sum_l;

    nxt.sum_l+=x.sum_l;
    nxt.sum_l+=y.sum_l;
    nxt.sum_l+=(v->color)*y.len;

    nxt.sum_r+=x.sum_r;
    nxt.sum_r+=y.sum_l;
    nxt.sum_r+=(v->color)*y.len;

    nxt.md=max(x.md,y.md);

    return nxt;
  }
};

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  const size_t LIM = 1e6;
  TopTree<Vertex, Cluster, LIM> G;
  using Type = decltype(G)::Type;

  int n;
  cin>>n;

  vector<Vertex*> vs(n);
  for(int i=0;i<n;i++) vs[i]=G.create(Vertex(0,i+1));

  for(int i=1;i<n;i++){
    int p,d;
    cin>>p>>d;
    p--;
    G.link(vs[p],Cluster(d),vs[i]);
  }

  for(int i=0;i<n;i++){
    ll sum=i+1;

    G.set_vertex(vs[i],Vertex(1,i+1));
    auto rt=G.expose(vs[0]);
    assert(!rt->p);
    assert(rt->type==Type::Compress);
    assert(rt->dat.cnt==sum);
    //cout<<rt->dat.cnt<<" "<<sum<<endl;

    auto cc=rt;
    Vertex* center=nullptr;

    ll lv=0,rv=0;
    while(cc->type==Type::Compress){
      G.propagate(cc);

      if(0){
        cout<<endl;
        cout<<":"<<sum<<":"<<(cc->dat.sum_l)<<":"<<(cc->dat.sum_r)<<endl;;
        cout<<":"<<(cc->dat.md.cnt)<<" "<<(cc->dat.md.ptr->idx)<<endl;
        cout<<"  "<<(cc->ch[0]->dat.cnt)<<"+"<<(lv)<<endl;
        cout<<"  "<<(cc->ch[1]->dat.cnt)<<"+"<<(rv)<<endl;
        cout<<"  "<<(cc->q?cc->q->dat.md.cnt:0)<<endl;
        cout<<endl;
      }

      auto ll=cc->ch[0];
      if((ll->dat.cnt+lv)*2>sum){
        if(ll->type==Type::Edge){
          center=cc->dat.md.ptr;
          break;
        }
        rv+=cc->dat.md.cnt-ll->dat.cnt;
        cc=(decltype(cc))ll->dat.md.ptr->handle;
        continue;
      }

      auto rr=cc->ch[1];
      if((rr->dat.cnt+rv)*2>sum){
        if(rr->type==Type::Edge){
          center=cc->dat.md.ptr;
          break;
        }
        lv+=cc->dat.md.cnt-rr->dat.cnt;
        cc=(decltype(cc))rr->dat.md.ptr->handle;
        continue;
      }

      auto mm=cc->q;
      if(mm and mm->dat.md.cnt*2>sum){
        rv+=lv;lv=0;
        rv+=cc->dat.md.cnt-mm->dat.cnt;
        cc=(decltype(cc))mm->dat.md.ptr->handle;
        continue;
      }

      center=cc->dat.md.ptr;
      break;
    }
    // cout<<center->idx<<":";
    cout<<G.get_subtree(center).ans<<newl;

    if(0){
      for(int j=0;j<n;j++)
        cout<<j+1<<":"<<G.get_subtree(vs[j]).ans<<newl;
      cout<<endl;
    }
  }

  return 0;
}
accuracy: 0.35135135135135137
time_ms: 1070
memory_kb: 147272
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}

template<typename F> struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args> decltype(auto) operator() (Args&&... args) const {return F::operator()(*this,forward<Args>(args)...);}
};
template<typename F> inline decltype(auto) MFP(F&& f){return FixPoint<F>(forward<F>(f));}

namespace tree_functions{
  using Tree=vector<vector<int>>;

  //A[root]=-1,A[v]=parent(v)
  vector<int> parent(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p)->void{
          A[u]=p;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u);}
          }
        }
        )(root,-1);
    return A;
  }

  //A[root]=0,A[v]=A[parent(v)]+1
  vector<int> depth(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p,int d)->void{
          A[u]=d++;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u,d);}
          }
        }
        )(root,-1,0);
    return A;
  }

  //A[i]=|{j|j is a descendant of i}|
  vector<int> cnt_dsc(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p)->int{
          A[u]=1;
          for(auto &v:edge[u]){
            if(v!=p){A[u]+=dfs(v,u);}
          }
          return A[u];
        }
        )(root,-1);
    return A;
  }
  
  //sort edges by the number of descendants
  //parent,heavy child,light child (root doesn't have a parent)
  void heavy_sort(Tree &edge,int root=0){
    int N=edge.size();
    vector<int> num=cnt_dsc(edge,root);
    for(int i=0;i<N;i++){
      sort(edge[i].begin(),edge[i].end(),[&](int a,int b){return num[a]>num[b];});
    }
  }

  //A[i]=root of heavy edge
  vector<int> HLD(Tree &edge,int root=0){
    heavy_sort(edge,root);
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p,int d)->void{
          A[u]=d;
          bool heavy=true;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u,heavy?d:v); heavy=false;}
          }
        }
        )(root,-1,root);
    return A;
  }

  vector<int> first_order(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    int idx=0;
    MFP(
        [&](auto dfs,int u,int p)->void{
          A[idx++]=u;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u);}
          }
        }
        )(root,-1);
    return A;
  }

  vector<int> last_order(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    int idx=0;
    MFP(
        [&](auto dfs,int u,int p)->void{
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u);}
          }
          A[idx++]=u;
        }
        )(root,-1);
    return A;
  }

  //max(dist(v,from)),argmax(dist(v,from))
  pair<int,int> distant_node(const Tree &edge,int from){
    pair<int,int> ret(0,from);
    MFP(
        [&](auto dfs,int u,int p,int d)->void{
          ret=max(ret,pair<int,int>(d,u));
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u,d+1);}
          }
        }
        )(0,-1,0);
    return ret;
  }
  
  //middle of wight   one or two
  vector<int> centroid(const Tree &edge){
    vector<int> ret;
    int N=edge.size();
    MFP(
        [&](auto dfs,int u,int p)->int{
          int mx=0,sum=1;
          for(auto &v:edge[u]){
            if(v!=p){
              int tmp=dfs(v,u);
              sum+=tmp;
              mx=max(mx,tmp);
            }
          }
          mx=max(mx,N-sum);
          if(mx*2<=N){ret.push_back(u);}
          return sum;
        }
        )(0,-1);
    sort(ret.begin(),ret.end());
    return ret;
  }

  //middle of distance   one or two
  vector<int> center(const Tree &edge){
    vector<int> ret;
    int N=edge.size();
    int u=distant_node(edge,0).S;
    int v=distant_node(edge,u).S;
    vector<int> d1=depth(edge,u),d2=depth(edge,v);
    int dm=d1[v];
    for(int i=0;i<N;i++){
      if(d1[i]+d2[i]==dm && abs(d1[i]-d2[i])<=1){ret.push_back(i);}
    }
    return ret;
  }
  
  //A[i]=centroid of up-tree
  vector<int> CRD(const Tree &edge){
    vector<int> A(edge.size(),-2);
    int sz,ctr;
    auto size_of_subtree=
      MFP(
          [&](auto dfs,int u,int p)->int{
            int sum=1;
            for(auto &v:edge[u]){
              if(v!=p && A[v]==-2){sum+=dfs(v,u);}
            }
            return sum;
          }
          );
    auto centroid_of_subtree=
      MFP(
          [&](auto dfs,int u,int p)->int{
            int mx=0,sum=1;
            for(auto &v:edge[u]){
              if(v!=p && A[v]==-2){
                int tmp=dfs(v,u);
                mx=max(mx,tmp);
                sum+=tmp;
              }
            }
            mx=max(mx,sz-sum);
            if(mx*2<=sz){ctr=u;}
            return sum;
          }
          );
    MFP(
        [&](auto dfs,int u,int p)->void{
          sz=size_of_subtree(u,-1);
          centroid_of_subtree(u,-1);
          u=ctr;
          A[u]=p;
          for(auto &v:edge[u]){
            if(A[v]==-2){dfs(v,u);}
          }
        }
        )(0,-1);
    return A;
  }
};
using namespace tree_functions;

//BEGIN CUT HERE
template <typename T,typename E>
struct SegmentTree{
  using F = function<T(T,T)>;
  using G = function<T(T,E)>;
  using H = function<E(E,E)>;
  int n,height;
  F f;
  G g;
  H h;
  T ti;
  E ei;
  vector<T> dat;
  vector<E> laz;
  SegmentTree(F f,G g,H h,T ti,E ei):
    f(f),g(g),h(h),ti(ti),ei(ei){}

  void init(int n_){
    n=1;height=0;
    while(n<n_) n<<=1,height++;
    dat.assign(2*n,ti);
    laz.assign(2*n,ei);
  }

  void build(const vector<T> &v){
    int n_=v.size();
    init(n_);
    for(int i=0;i<n_;i++) dat[n+i]=v[i];
    for(int i=n-1;i;i--)
      dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);
  }

  inline T reflect(int k){
    return laz[k]==ei?dat[k]:g(dat[k],laz[k]);
  }

  inline void propagate(int k){
    if(laz[k]==ei) return;
    laz[(k<<1)|0]=h(laz[(k<<1)|0],laz[k]);
    laz[(k<<1)|1]=h(laz[(k<<1)|1],laz[k]);
    dat[k]=reflect(k);
    laz[k]=ei;
  }

  inline void thrust(int k){
    for(int i=height;i;i--) propagate(k>>i);
  }

  inline void recalc(int k){
    while(k>>=1)
      dat[k]=f(reflect((k<<1)|0),reflect((k<<1)|1));
  }

  void update(int a,int b,E x){
    if(a>=b) return;
    thrust(a+=n);
    thrust(b+=n-1);
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
      if(l&1) laz[l]=h(laz[l],x),l++;
      if(r&1) --r,laz[r]=h(laz[r],x);
    }
    recalc(a);
    recalc(b);
  }

  void set_val(int a,T x){
    thrust(a+=n);
    dat[a]=x;laz[a]=ei;
    recalc(a);
  }

  T query(int a,int b){
    if(a>=b) return ti;
    thrust(a+=n);
    thrust(b+=n-1);
    T vl=ti,vr=ti;
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,reflect(l++));
      if(r&1) vr=f(reflect(--r),vr);
    }
    return f(vl,vr);
  }

  template<typename C>
  int find(int st,C &check,T &acc,int k,int l,int r){
    if(l+1==r){
      acc=f(acc,reflect(k));
      return check(acc)?k-n:-1;
    }
    propagate(k);
    int m=(l+r)>>1;
    if(m<=st) return find(st,check,acc,(k<<1)|1,m,r);
    if(st<=l&&!check(f(acc,dat[k]))){
      acc=f(acc,dat[k]);
      return -1;
    }
    int vl=find(st,check,acc,(k<<1)|0,l,m);
    if(~vl) return vl;
    return find(st,check,acc,(k<<1)|1,m,r);
  }

  template<typename C>
  int find(int st,C &check){
    T acc=ti;
    return find(st,check,acc,1,0,n);
  }
};
//END CUT HERE

vector<int> inv(const vector<int> &A){
  int N=A.size();
  vector<int> ret(N);
  for(int i=0;i<N;i++){ret[A[i]]=i;}
  return ret;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N;
  cin>>N;
  if(N==1){cout<<0<<endl; return 0;}
  vector<vector<int>> edge(N);
  vector<ll> D(N,0);
  for(int i=1;i<N;i++){
    int p,d;
    cin>>p>>d;
    p--;
    edge[i].push_back(p);
    edge[p].push_back(i);
    D[i]=d;
  }

  auto leaf=[&](int v){return (v==0 && edge[v].empty()) || (v!=0 && edge[v].size()<2);};
  vector<ll> d=D;
  vector<int> hl=HLD(edge);
  vector<int> fr=first_order(edge);
  vector<int> idx=inv(fr);
  vector<int> ls=last_order(edge);
  vector<int> sub(N,fr.back());
  vector<int> bt(N);
  vector<int> mx(N,fr[1]);
  auto f1=[](int a,int b){return a+b;};
  auto f2=[](ll a,ll b){return a+b;};
  SegmentTree<int,int> seg(f1,f1,f1,0,0);
  SegmentTree<ll,ll> dep(f2,f2,f2,0,0);
  SegmentTree<int,int> num(f1,f1,f1,0,0);
  seg.build(vector<int>(N,0));
  dep.build(vector<ll>(N,0));
  num.build(vector<int>(N,0));
  for(int i=1;i<N;i++){mx[i]=(leaf(i)?-1:edge[i][1]);}
  for(int i=0;i<N;i++){bt[hl[fr[i]]]=i;}
  for(int i=0,tmp=-1;i<N;i++){
    if(leaf(ls[i])){tmp=ls[i];}
    sub[ls[i]]=idx[tmp]+1;
  }
  for(auto &u:fr){for(auto &v:edge[u]){if(idx[v]>idx[u]){D[v]+=D[u];}}}
  
  auto cnt=[&](int a){return seg.query(idx[a],sub[a]);};
  ll sum=0;
  auto query=
    [&](int k){
      ll ans=sum;
      int u=0;
      while(1){
        int lf=idx[u],rg=bt[u]+1;
        while(rg-lf>1){
          int mid=(lf+rg)/2;
          if(cnt(fr[mid])*2>=k){lf=mid;}
          else{rg=mid;}
        }
        lf=fr[lf];
        rg=bt[u]+1;
        ans+=(D[lf]-D[u])*(k-cnt(u));
        ans-=2*dep.query(idx[u],idx[lf])-(D[lf]+D[u])*num.query(idx[u],idx[lf]);        
        ans-=(D[lf]-D[u])*num.query(idx[lf],rg);
        u=lf;        
        if(leaf(u) || cnt(mx[u])*2<=k){break;}
        ans+=(k-2*cnt(mx[u]))*d[mx[u]];
        u=mx[u];
      }
      cout<<ans<<endl;
    };
  auto add=
    [&](int a){
      sum+=D[a];
      seg.update(idx[a],idx[a]+1,1);
      dep.update(idx[a],idx[a]+1,D[a]);
      num.update(idx[a],idx[a]+1,1);
      a=hl[a];
      while(a!=0){
        int v=a;
        a=edge[a][0];
        dep.update(idx[a],idx[a]+1,D[a]);
        num.update(idx[a],idx[a]+1,1);
        if(cnt(mx[a])<cnt(v)){mx[a]=v;}
        a=hl[a];
      }
    };
  for(int i=0;i<N;){add(i); query(++i);}
  
  
  return 0;
}
accuracy: 1
time_ms: 1350
memory_kb: 48196
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}

template<typename F> struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args> decltype(auto) operator() (Args&&... args) const {return F::operator()(*this,forward<Args>(args)...);}
};
template<typename F> inline decltype(auto) MFP(F&& f){return FixPoint<F>(forward<F>(f));}

namespace tree_functions{
  using Tree=vector<vector<int>>;

  //A[root]=-1,A[v]=parent(v)
  vector<int> parent(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p)->void{
          A[u]=p;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u);}
          }
        }
        )(root,-1);
    return A;
  }

  //A[root]=0,A[v]=A[parent(v)]+1
  vector<int> depth(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p,int d)->void{
          A[u]=d++;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u,d);}
          }
        }
        )(root,-1,0);
    return A;
  }

  //A[i]=|{j|j is a descendant of i}|
  vector<int> cnt_dsc(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p)->int{
          A[u]=1;
          for(auto &v:edge[u]){
            if(v!=p){A[u]+=dfs(v,u);}
          }
          return A[u];
        }
        )(root,-1);
    return A;
  }
  
  //sort edges by the number of descendants
  //parent,heavy child,light child (root doesn't have a parent)
  void heavy_sort(Tree &edge,int root=0){
    int N=edge.size();
    vector<int> num=cnt_dsc(edge,root);
    for(int i=0;i<N;i++){
      sort(edge[i].begin(),edge[i].end(),[&](int a,int b){return num[a]>num[b];});
    }
  }

  //A[i]=root of heavy edge
  vector<int> HLD(Tree &edge,int root=0){
    heavy_sort(edge,root);
    vector<int> A(edge.size(),-1);
    MFP(
        [&](auto dfs,int u,int p,int d)->void{
          A[u]=d;
          bool heavy=true;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u,heavy?d:v); heavy=false;}
          }
        }
        )(root,-1,root);
    return A;
  }

  vector<int> first_order(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    int idx=0;
    MFP(
        [&](auto dfs,int u,int p)->void{
          A[idx++]=u;
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u);}
          }
        }
        )(root,-1);
    return A;
  }

  vector<int> last_order(const Tree &edge,int root=0){
    vector<int> A(edge.size(),-1);
    int idx=0;
    MFP(
        [&](auto dfs,int u,int p)->void{
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u);}
          }
          A[idx++]=u;
        }
        )(root,-1);
    return A;
  }

  //max(dist(v,from)),argmax(dist(v,from))
  pair<int,int> distant_node(const Tree &edge,int from){
    pair<int,int> ret(0,from);
    MFP(
        [&](auto dfs,int u,int p,int d)->void{
          ret=max(ret,pair<int,int>(d,u));
          for(auto &v:edge[u]){
            if(v!=p){dfs(v,u,d+1);}
          }
        }
        )(0,-1,0);
    return ret;
  }
  
  //middle of wight   one or two
  vector<int> centroid(const Tree &edge){
    vector<int> ret;
    int N=edge.size();
    MFP(
        [&](auto dfs,int u,int p)->int{
          int mx=0,sum=1;
          for(auto &v:edge[u]){
            if(v!=p){
              int tmp=dfs(v,u);
              sum+=tmp;
              mx=max(mx,tmp);
            }
          }
          mx=max(mx,N-sum);
          if(mx*2<=N){ret.push_back(u);}
          return sum;
        }
        )(0,-1);
    sort(ret.begin(),ret.end());
    return ret;
  }

  //middle of distance   one or two
  vector<int> center(const Tree &edge){
    vector<int> ret;
    int N=edge.size();
    int u=distant_node(edge,0).S;
    int v=distant_node(edge,u).S;
    vector<int> d1=depth(edge,u),d2=depth(edge,v);
    int dm=d1[v];
    for(int i=0;i<N;i++){
      if(d1[i]+d2[i]==dm && abs(d1[i]-d2[i])<=1){ret.push_back(i);}
    }
    return ret;
  }
  
  //A[i]=centroid of up-tree
  vector<int> CRD(const Tree &edge){
    vector<int> A(edge.size(),-2);
    int sz,ctr;
    auto size_of_subtree=
      MFP(
          [&](auto dfs,int u,int p)->int{
            int sum=1;
            for(auto &v:edge[u]){
              if(v!=p && A[v]==-2){sum+=dfs(v,u);}
            }
            return sum;
          }
          );
    auto centroid_of_subtree=
      MFP(
          [&](auto dfs,int u,int p)->int{
            int mx=0,sum=1;
            for(auto &v:edge[u]){
              if(v!=p && A[v]==-2){
                int tmp=dfs(v,u);
                mx=max(mx,tmp);
                sum+=tmp;
              }
            }
            mx=max(mx,sz-sum);
            if(mx*2<=sz){ctr=u;}
            return sum;
          }
          );
    MFP(
        [&](auto dfs,int u,int p)->void{
          sz=size_of_subtree(u,-1);
          centroid_of_subtree(u,-1);
          u=ctr;
          A[u]=p;
          for(auto &v:edge[u]){
            if(A[v]==-2){dfs(v,u);}
          }
        }
        )(0,-1);
    return A;
  }
};
using namespace tree_functions;

//BEGIN CUT HERE
template <typename T,typename E>
struct SegmentTree{
  using F = function<T(T,T)>;
  using G = function<T(T,E)>;
  using H = function<E(E,E)>;
  int n,height;
  F f;
  G g;
  H h;
  T ti;
  E ei;
  vector<T> dat;
  vector<E> laz;
  SegmentTree(F f,G g,H h,T ti,E ei):
    f(f),g(g),h(h),ti(ti),ei(ei){}

  void init(int n_){
    n=1;height=0;
    while(n<n_) n<<=1,height++;
    dat.assign(2*n,ti);
    laz.assign(2*n,ei);
  }

  void build(const vector<T> &v){
    int n_=v.size();
    init(n_);
    for(int i=0;i<n_;i++) dat[n+i]=v[i];
    for(int i=n-1;i;i--)
      dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);
  }

  inline T reflect(int k){
    return laz[k]==ei?dat[k]:g(dat[k],laz[k]);
  }

  inline void propagate(int k){
    if(laz[k]==ei) return;
    laz[(k<<1)|0]=h(laz[(k<<1)|0],laz[k]);
    laz[(k<<1)|1]=h(laz[(k<<1)|1],laz[k]);
    dat[k]=reflect(k);
    laz[k]=ei;
  }

  inline void thrust(int k){
    for(int i=height;i;i--) propagate(k>>i);
  }

  inline void recalc(int k){
    while(k>>=1)
      dat[k]=f(reflect((k<<1)|0),reflect((k<<1)|1));
  }

  void update(int a,int b,E x){
    if(a>=b) return;
    thrust(a+=n);
    thrust(b+=n-1);
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
      if(l&1) laz[l]=h(laz[l],x),l++;
      if(r&1) --r,laz[r]=h(laz[r],x);
    }
    recalc(a);
    recalc(b);
  }

  void set_val(int a,T x){
    thrust(a+=n);
    dat[a]=x;laz[a]=ei;
    recalc(a);
  }

  T query(int a,int b){
    if(a>=b) return ti;
    thrust(a+=n);
    thrust(b+=n-1);
    T vl=ti,vr=ti;
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,reflect(l++));
      if(r&1) vr=f(reflect(--r),vr);
    }
    return f(vl,vr);
  }

  template<typename C>
  int find(int st,C &check,T &acc,int k,int l,int r){
    if(l+1==r){
      acc=f(acc,reflect(k));
      return check(acc)?k-n:-1;
    }
    propagate(k);
    int m=(l+r)>>1;
    if(m<=st) return find(st,check,acc,(k<<1)|1,m,r);
    if(st<=l&&!check(f(acc,dat[k]))){
      acc=f(acc,dat[k]);
      return -1;
    }
    int vl=find(st,check,acc,(k<<1)|0,l,m);
    if(~vl) return vl;
    return find(st,check,acc,(k<<1)|1,m,r);
  }

  template<typename C>
  int find(int st,C &check){
    T acc=ti;
    return find(st,check,acc,1,0,n);
  }
};
//END CUT HERE

vector<int> inv(const vector<int> &A){
  int N=A.size();
  vector<int> ret(N);
  for(int i=0;i<N;i++){ret[A[i]]=i;}
  return ret;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N;
  cin>>N;
  if(N==1){cout<<0<<endl; return 0;}
  vector<vector<int>> edge(N);
  vector<ll> D(N,0);
  for(int i=1;i<N;i++){
    int p,d;
    cin>>p>>d;
    p--;
    edge[i].push_back(p);
    edge[p].push_back(i);
    D[i]=d;
  }

  auto leaf=[&](int v){return (v==0 && edge[v].empty()) || (v!=0 && edge[v].size()<2);};
  vector<ll> d=D;
  vector<int> hl=HLD(edge);
  vector<int> fr=first_order(edge);
  vector<int> idx=inv(fr);
  vector<int> ls=last_order(edge);
  vector<int> sub(N,fr.back());
  vector<int> bt(N);
  vector<int> mx(N,fr[1]);
  auto f1=[](int a,int b){return a+b;};
  auto f2=[](ll a,ll b){return a+b;};
  SegmentTree<int,int> seg(f1,f1,f1,0,0);
  SegmentTree<ll,ll> dep(f2,f2,f2,0,0);
  SegmentTree<int,int> num(f1,f1,f1,0,0);
  seg.build(vector<int>(N,0));
  dep.build(vector<ll>(N,0));
  num.build(vector<int>(N,0));
  for(int i=1;i<N;i++){mx[i]=(leaf(i)?-1:edge[i][1]);}
  for(int i=0;i<N;i++){bt[hl[fr[i]]]=i;}
  for(int i=0,tmp=-1;i<N;i++){
    if(leaf(ls[i])){tmp=ls[i];}
    sub[ls[i]]=idx[tmp]+1;
  }
  for(auto &u:fr){for(auto &v:edge[u]){if(idx[v]>idx[u]){D[v]+=D[u];}}}
  
  auto cnt=[&](int a){return seg.query(idx[a],sub[a]);};
  ll sum=0;
  auto query=
    [&](int k){
      ll ans=sum;
      int u=0;
      while(1){
        int lf=idx[u],rg=bt[u]+1;
        while(rg-lf>1){
          int mid=(lf+rg)/2;
          if(cnt(fr[mid])*2>=k){lf=mid;}
          else{rg=mid;}
        }
        lf=fr[lf];
        rg=bt[u]+1;
        ans+=(D[lf]-D[u])*(k-cnt(u));
        ans-=2*dep.query(idx[u],idx[lf])-(D[lf]+D[u])*num.query(idx[u],idx[lf]);        
        ans-=(D[lf]-D[u])*num.query(idx[lf],rg);
        u=lf;        
        if(leaf(u) || cnt(mx[u])*2<=k){break;}
        ans+=(k-2*cnt(mx[u]))*d[mx[u]];
        u=mx[u];
      }
      cout<<ans<<endl;
    };
  auto add=
    [&](int a){
      sum+=D[a];
      seg.update(idx[a],idx[a]+1,1);
      dep.update(idx[a],idx[a]+1,D[a]);
      num.update(idx[a],idx[a]+1,1);
      a=hl[a];
      while(a!=0){
        int v=a;
        a=edge[a][0];
        dep.update(idx[a],idx[a]+1,D[a]);
        num.update(idx[a],idx[a]+1,1);
        if(cnt(mx[a])<cnt(edge[a][1])){mx[a]=edge[a][a==0?0:1];}
        if(cnt(mx[a])<cnt(v)){mx[a]=v;}
        a=hl[a];
      }
    };
  for(int i=0;i<N;){add(i); query(++i);}
  
  
  return 0;
}
accuracy: 1
time_ms: 1550
memory_kb: 48308
final_rank: 12