Problem p02686 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>

using namespace std;
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)

typedef long long ll;
typedef pair<ll, ll> P;
const ll INF = 1LL << 60;

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

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

ll modpow(ll a, ll n, ll mod) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}

bool ok(vector<pair<int, int>> v) {

  sort(v.rbegin(), v.rend());

  int now = 0;
  rep(i, v.size()) {

    if (now + v[i].first < 0) {
      return false;
    }

    now += v[i].second;
  }

  return true;
}

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

  int n;
  cin >> n;

  vector<pair<int, int>> L, R;

  int sum_h = 0;
  rep(i, n) {
    string s;
    cin >> s;
    int h = 0;
    int b = 0;
    rep(j, s.length()) {
      if (s[j] == '(') {
        h++;
        chmin(b, h);
      } else {
        h--;
        chmin(b, h);
      }
    }
    if (h >= 0) {
      L.emplace_back(b, h);
    } else {
      R.emplace_back(b - h, -h);
    }
    sum_h += h;
  }

  if (sum_h != 0) {
    cout << "No" << endl;
    return 0;
  }

  if (ok(L) && ok(R)) {
    cout << "Yes" << endl;
  } else {
    cout << "No" << endl;
  }

  return 0;
}


Error: 0

Fixed submission:

#include <bits/stdc++.h>

using namespace std;
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)

typedef long long ll;
typedef pair<ll, ll> P;
const ll INF = 1LL << 60;

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

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

ll modpow(ll a, ll n, ll mod) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}

tuple<int, ll, int> max(tuple<int, ll, int> a, tuple<int, ll, int> b) {

  if (get<1>(a) < get<1>(b)) {
    return b;
  } else {
    return a;
  }
}

struct SegmentTree {
private:
  int n;
  vector<tuple<int, ll, int>> node;

public:
  // 元配列 v をセグメント木で表現する
  SegmentTree(vector<tuple<int, ll, int>> v) {
    // 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
    // セグメント木全体で必要なノード数は 2n-1 個である
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;

    rep(i, 2 * n - 1) { node.push_back(make_tuple(0, -1e7, 0)); }

    // 最下段に値を入れたあとに、下の段から順番に値を入れる
    // 値を入れるには、自分の子の 2 値を参照すれば良い
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  void update(int x, ll val) {
    // 最下段のノードにアクセスする
    x += (n - 1);

    // 最下段のノードを更新したら、あとは親に上って更新していく
    get<1>(node[x]) = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  // 要求区間 [a, b) 中の要素の最大値を答える
  // k := 自分がいるノードのインデックス
  // 対象区間は [l, r) にあたる
  tuple<int, ll, int> getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない -> 適当に返す
    if (r <= a || b <= l)
      return make_tuple(-10000000, -10000000, -10000000);

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (a <= l && r <= b)
      return node[k];

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    auto vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    auto vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }
};

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

  int n;
  cin >> n;

  vector<tuple<int, ll, int>> vec;
  rep(i, n) {

    string s;
    cin >> s;

    int cnt = 0;
    int val_min = 0;
    rep(j, s.length()) {
      if (s[j] == '(') {
        cnt++;
        chmin(val_min, int(cnt));
      } else {
        cnt--;
        chmin(val_min, int(cnt));
      }
    }

    vec.push_back(make_tuple(val_min, cnt, i));
  }

  sort(vec.begin(), vec.end());

  rep(i, n) { get<2>(vec[i]) = i; }

  SegmentTree st(vec);

  int now = 0;
  rep(i, n) {

    int ind =
        lower_bound(vec.begin(), vec.end(), make_tuple(-now, -1e7 + 1, 0)) -
        vec.begin();

    auto v = st.getmax(ind, n);

    if (get<1>(v) < -10000000) {
      cout << "No" << endl;
      return 0;
    }
    now += get<1>(v);

    st.update(get<2>(v), -1e7);

    if (now < 0) {
      cout << "No" << endl;
      return 0;
    }
  }

  if (now != 0) {
    cout << "No" << endl;
    return 0;
  }

  cout << "Yes" << endl;

  return 0;
}