Problem p03176 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define RFOR(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define REP(i, n) for (int i = 0; i < (n); i++)
#define RREP(i, n) for (int i = (n)-1; i >= 0; i--)
typedef long long LL;
const int MAX_N = 1 << 17;
// セグメント木を持つグローバル配列
LL n, dat[2 * MAX_N - 1];
// 初期化
void init(int n_) {
  // 簡単のために要素数を2のべき乗に
  n = 1;
  while (n < n_)
    n *= 2;
  // 全ての値をINT_MAXに
  for (int i = 0; i < 2 * n - 1; i++)
    dat[i] = 1e12;
}

// k番目の値(0-index)をaに変更
void update(int k, LL a) {
  // 葉の節点
  k += n - 1;
  dat[k] = a;
  // 登りながら更新
  while (k > 0) {
    k = (k - 1) / 2;
    dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
  }
}

//[a,b]の最小値を求める
// 後ろの方の引数は計算の簡単のための引数
// kは節点番号，l.rはその節点が[l,r]に対応づいていることを表す
// 従って外からはquery(a,b,0,0,n-1)として呼ぶ
LL query(int a, int b, LL k, int l, int r) {
  //[a,b]と[l,r]が交差しなければINT_MAX
  if (r < a || b < l)
    return 1e12;
  //[a,b]が[l,r]を完全に含んでいればこの節点の値
  if (a <= l && r <= b)
    return dat[k];
  else {
    // そうでなければ2つの子の最小値
    LL vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
    LL vr = query(a, b, k * 2 + 2, (l + r) / 2 + 1, r);
    return min(vl, vr);
  }
}

int h[200001];
LL a[200001];
typedef pair<int, int> P;
vector<P> v;
LL dp[200001];

int main() {
  int N;
  cin >> N;
  init(200010);
  REP(i, N + 5) { update(i, 0); }
  REP(i, N) {
    cin >> h[i];
    v.push_back(P(h[i], i));
  }
  sort(v.begin(), v.end());
  REP(i, N) { cin >> a[i]; }
  REP(i, v.size()) {
    int x = v[i].second;
    // cout<<v[i].first<<v[i].second<<endl;
    if (x == 0) {
      dp[x] = a[x];
      update(x, -dp[x]);
    } else {
      LL aa = query(0, x - 1, 0, 0, n - 1);
      dp[x] = a[x] - aa;
      update(x, -dp[x]);
    }
  }
  LL ans = 0;
  REP(i, N) {
    // cout<<dp[i]<<endl;
    ans = max(ans, dp[i]);
  }

  cout << ans << endl;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define RFOR(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define REP(i, n) for (int i = 0; i < (n); i++)
#define RREP(i, n) for (int i = (n)-1; i >= 0; i--)
typedef long long LL;
const int MAX_N = 1 << 20;
// セグメント木を持つグローバル配列
LL n, dat[2 * MAX_N - 1];
// 初期化
void init(int n_) {
  // 簡単のために要素数を2のべき乗に
  n = 1;
  while (n < n_)
    n *= 2;
  // 全ての値をINT_MAXに
  for (int i = 0; i < 2 * n - 1; i++)
    dat[i] = 1e12;
}

// k番目の値(0-index)をaに変更
void update(int k, LL a) {
  // 葉の節点
  k += n - 1;
  dat[k] = a;
  // 登りながら更新
  while (k > 0) {
    k = (k - 1) / 2;
    dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
  }
}

//[a,b]の最小値を求める
// 後ろの方の引数は計算の簡単のための引数
// kは節点番号，l.rはその節点が[l,r]に対応づいていることを表す
// 従って外からはquery(a,b,0,0,n-1)として呼ぶ
LL query(int a, int b, LL k, int l, int r) {
  //[a,b]と[l,r]が交差しなければINT_MAX
  if (r < a || b < l)
    return 1e12;
  //[a,b]が[l,r]を完全に含んでいればこの節点の値
  if (a <= l && r <= b)
    return dat[k];
  else {
    // そうでなければ2つの子の最小値
    LL vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
    LL vr = query(a, b, k * 2 + 2, (l + r) / 2 + 1, r);
    return min(vl, vr);
  }
}

int h[200001];
LL a[200001];
typedef pair<int, int> P;
vector<P> v;
LL dp[200001];

int main() {
  int N;
  cin >> N;
  init(200010);
  REP(i, N + 5) { update(i, 0); }
  REP(i, N) {
    cin >> h[i];
    v.push_back(P(h[i], i));
  }
  sort(v.begin(), v.end());
  REP(i, N) { cin >> a[i]; }
  REP(i, v.size()) {
    int x = v[i].second;
    // cout<<v[i].first<<v[i].second<<endl;
    if (x == 0) {
      dp[x] = a[x];
      update(x, -dp[x]);
    } else {
      LL aa = query(0, x - 1, 0, 0, n - 1);
      dp[x] = a[x] - aa;
      update(x, -dp[x]);
    }
  }
  LL ans = 0;
  REP(i, N) {
    // cout<<dp[i]<<endl;
    ans = max(ans, dp[i]);
  }

  cout << ans << endl;
}