Problem p03941 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int __SIZE = 1 << 18;
char ibuf[__SIZE], *iS, *iT;

#define ge                                                                     \
  (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),               \
               (iS == iT ? EOF : *iS++))                                       \
            : *iS++)
#define ri read_int()
#define rl read_ll()
#define FILE(s) freopen(s "in", "r", stdin), freopen(s "out", "w", stdout)

template <typename T> inline void read(T &x) {
  char ch, t = 0;
  x = 0;
  while (!isdigit(ch = ge))
    t |= ch == '-';
  while (isdigit(ch))
    x = x * 10 + (ch ^ 48), ch = ge;
  x = t ? -x : x;
}
inline int read_int() {
  int x;
  return read(x), x;
}
inline ll read_ll() {
  ll x;
  return read(x), x;
}

template <typename T> inline void chkmin(T &a, T b) { a = a < b ? a : b; }

const int MAXN = 132000;

int tot;
int fi[MAXN];
int ne[MAXN << 1];
int to[MAXN << 1];
int vl[MAXN << 1];

inline void Link(int u, int v, int w) {
  tot++;
  to[tot] = v;
  vl[tot] = w;
  ne[tot] = fi[u];
  fi[u] = tot;
}

struct Node {
  ll a, b;

  Node() {}
  Node(ll a, ll b) : a(a), b(b) {}

  friend bool operator<(Node a, Node b) { return a.a < b.a; }
} A[MAXN * 20], tmp[MAXN * 20];

int L[MAXN];
int R[MAXN];
int n;
int cnt;

inline void gb_Merge(int l1, int r1, int l2, int r2) {
  int l = l1, r = r2, k = l1;
  while (l1 <= r1 && l2 <= r2) {
    if (A[l1] < A[l2])
      tmp[k++] = A[l1++];
    else
      tmp[k++] = A[l2++];
  }
  while (l1 <= r1)
    tmp[k++] = A[l1++];
  while (l2 <= r2)
    tmp[k++] = A[l2++];
  while (k > l)
    --k, A[k] = tmp[k];
}

inline void Merge(int x, int l, int r, ll lim) {
  int pl1 = cnt + 1, pr1 = cnt;
  ll mi = 1LL << 61;
  for (int i = L[l], j = L[r] - 1; i <= R[l]; ++i) {
    while (j < R[r] && A[i].b + A[j + 1].a <= lim)
      ++j, mi = mi < A[j].b ? mi : A[j].b;
    if (j < L[r])
      continue;
    A[++pr1] = Node(A[i].a, mi);
  }
  cnt = pr1;
  int pl2 = cnt + 1, pr2 = cnt;
  mi = 1LL << 61, swap(l, r);
  for (int i = L[l], j = L[r] - 1; i <= R[l]; ++i) {
    while (j < R[r] && A[i].b + A[j + 1].a <= lim)
      ++j, mi = mi < A[j].b ? mi : A[j].b;
    if (j < L[r])
      continue;
    A[++pr2] = Node(A[i].a, A[j].b);
  }
  cnt = pr2, L[x] = pl1, R[x] = pr2;
  if (L[x] > R[x])
    return;
  gb_Merge(pl1, pr1, pl2, pr2);
  int Sum = 0;
  for (int i = L[x] + 1; i <= R[x]; ++i) {
    if (A[i].b >= A[L[x] + Sum].b)
      continue;
    else
      ++Sum, A[L[x] + Sum] = A[i];
  }
  cnt = R[x] = L[x] + Sum;
  /*
  cout << lim << endl;
  for(int i = L[x]; i <= R[x]; i++) {
          cout << A[i].a << ' ' << A[i].b << endl;
  }
  cout << endl;
  */
}

inline void dfs(int x, ll lim) {
  if (!fi[x]) {
    L[x] = R[x] = ++cnt;
    A[cnt] = Node(0, 0);
  } else {
    L[x] = cnt + 1, R[x] = cnt;
    int val, Ls = to[fi[x]], Rs = to[ne[fi[x]]];

    dfs(Ls, lim), val = vl[fi[x]];
    // cout << L[Ls] << ' ' << R[Ls] << endl;
    if (L[Ls] > R[Ls])
      return;
    for (int i = L[Ls]; i <= R[Ls]; i++)
      A[i].a += val, A[i].b += val;

    dfs(Rs, lim), val = vl[ne[fi[x]]];
    if (L[Rs] > R[Rs])
      return;
    for (int i = L[Rs]; i <= R[Rs]; i++)
      A[i].a += val, A[i].b += val;

    Merge(x, Ls, Rs, lim);
  }
}

inline bool chk(ll lim) {
  cnt = 0, dfs(1, lim);
  return L[1] <= R[1];
}

int main() {
#ifndef ONLINE_JUDGE
  FILE("");
#endif
  n = ri;
  ll mx = 0;
  for (int i = 2; i <= n; i++) {
    int f = ri, v = ri;
    Link(f, i, v);
    mx += v;
  }
  ll l = 0, r = mx, res;
  while (l <= r) {
    ll mid = (l + r) >> 1;
    if (chk(mid))
      r = mid - 1, res = mid;
    else
      l = mid + 1;
  }
  printf("%lld\n", res);
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int __SIZE = 1 << 18;
char ibuf[__SIZE], *iS, *iT;

#define ge                                                                     \
  (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),               \
               (iS == iT ? EOF : *iS++))                                       \
            : *iS++)
#define ri read_int()
#define rl read_ll()
#define FILE(s) freopen(s "in", "r", stdin), freopen(s "out", "w", stdout)

template <typename T> inline void read(T &x) {
  char ch, t = 0;
  x = 0;
  while (!isdigit(ch = ge))
    t |= ch == '-';
  while (isdigit(ch))
    x = x * 10 + (ch ^ 48), ch = ge;
  x = t ? -x : x;
}
inline int read_int() {
  int x;
  return read(x), x;
}
inline ll read_ll() {
  ll x;
  return read(x), x;
}

template <typename T> inline void chkmin(T &a, T b) { a = a < b ? a : b; }

const int MAXN = 132000;

int tot;
int fi[MAXN];
int ne[MAXN << 1];
int to[MAXN << 1];
int vl[MAXN << 1];

inline void Link(int u, int v, int w) {
  tot++;
  to[tot] = v;
  vl[tot] = w;
  ne[tot] = fi[u];
  fi[u] = tot;
}

struct Node {
  ll a, b;

  Node() {}
  Node(ll a, ll b) : a(a), b(b) {}

  friend bool operator<(Node a, Node b) { return a.a < b.a; }
} A[MAXN * 20], tmp[MAXN * 20];

int L[MAXN];
int R[MAXN];
int n;
int cnt;

inline void gb_Merge(int l1, int r1, int l2, int r2) {
  int l = l1, r = r2, k = l1;
  while (l1 <= r1 && l2 <= r2) {
    if (A[l1] < A[l2])
      tmp[k++] = A[l1++];
    else
      tmp[k++] = A[l2++];
  }
  while (l1 <= r1)
    tmp[k++] = A[l1++];
  while (l2 <= r2)
    tmp[k++] = A[l2++];
  while (k > l)
    --k, A[k] = tmp[k];
}

inline void Merge(int x, int l, int r, ll lim) {
  int pl1 = cnt + 1, pr1 = cnt;
  ll mi = 1LL << 61;
  for (int i = L[l], j = L[r] - 1; i <= R[l]; ++i) {
    while (j < R[r] && A[i].b + A[j + 1].a <= lim)
      ++j, mi = mi < A[j].b ? mi : A[j].b;
    if (j < L[r])
      continue;
    A[++pr1] = Node(A[i].a, mi);
  }
  cnt = pr1;
  int pl2 = cnt + 1, pr2 = cnt;
  mi = 1LL << 61, swap(l, r);
  for (int i = L[l], j = L[r] - 1; i <= R[l]; ++i) {
    while (j < R[r] && A[i].b + A[j + 1].a <= lim)
      ++j, mi = mi < A[j].b ? mi : A[j].b;
    if (j < L[r])
      continue;
    A[++pr2] = Node(A[i].a, A[j].b);
  }
  cnt = pr2, L[x] = pl1, R[x] = pr2;
  if (L[x] > R[x])
    return;
  gb_Merge(pl1, pr1, pl2, pr2);
  int Sum = 0;
  for (int i = L[x] + 1; i <= R[x]; ++i) {
    if (A[i].b >= A[L[x] + Sum].b)
      continue;
    else
      ++Sum, A[L[x] + Sum] = A[i];
  }
  cnt = R[x] = L[x] + Sum;
  /*
  cout << lim << endl;
  for(int i = L[x]; i <= R[x]; i++) {
          cout << A[i].a << ' ' << A[i].b << endl;
  }
  cout << endl;
  */
}

inline void dfs(int x, ll lim) {
  if (!fi[x]) {
    L[x] = R[x] = ++cnt;
    A[cnt] = Node(0, 0);
  } else {
    L[x] = cnt + 1, R[x] = cnt;
    int val, Ls = to[fi[x]], Rs = to[ne[fi[x]]];

    dfs(Ls, lim), val = vl[fi[x]];
    // cout << L[Ls] << ' ' << R[Ls] << endl;
    if (L[Ls] > R[Ls])
      return;
    for (int i = L[Ls]; i <= R[Ls]; i++)
      A[i].a += val, A[i].b += val;

    dfs(Rs, lim), val = vl[ne[fi[x]]];
    if (L[Rs] > R[Rs])
      return;
    for (int i = L[Rs]; i <= R[Rs]; i++)
      A[i].a += val, A[i].b += val;

    Merge(x, Ls, Rs, lim);
  }
}

inline bool chk(ll lim) {
  cnt = 0, dfs(1, lim);
  return L[1] <= R[1];
}

int main() {
  n = ri;
  ll mx = 0;
  for (int i = 2; i <= n; i++) {
    int f = ri, v = ri;
    Link(f, i, v);
    mx += v;
  }
  ll l = 0, r = mx, res;
  while (l <= r) {
    ll mid = (l + r) >> 1;
    if (chk(mid))
      r = mid - 1, res = mid;
    else
      l = mid + 1;
  }
  printf("%lld\n", res);
  return 0;
}