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

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

bool cmp(pair<int, int> a, pair<int, int> b) { return a.second > b.second; }

signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  int n;
  cin >> n;
  vector<pair<int, int>> seqs(n);
  vector<pair<int, int>> begs, ends;
  for (int i = 0; i < n; ++i) {
    string s;
    cin >> s;
    stack<char> st;
    for (int j = 0; j < int(s.size()); ++j) {
      if (!st.empty()) {
        if (st.top() == '(' && s[j] == ')')
          st.pop();
        else
          st.push(s[j]);
      } else
        st.push(s[j]);
    }
    pair<int, int> seq = make_pair(0, 0);
    while (!st.empty()) {
      if (st.top() == ')')
        ++seq.first;
      else
        ++seq.second;
      st.pop();
    }
    seqs[i] = seq;
    if (seq.second - seq.first >= 0)
      begs.push_back(seq);
    else
      ends.push_back(seq);
  }
  sort(begs.begin(), begs.end());
  sort(ends.begin(), ends.end(), cmp);
  int b = 0;
  for (int i = 0; i < int(begs.size()); ++i) {
    b -= begs[i].first;
    if (b < 0) {
      cout << "No\\n";
      return 0;
    }
    b += begs[i].second;
  }
  for (int i = 0; i < int(ends.size()); ++i) {
    b -= ends[i].first;
    if (b < 0) {
      cout << "No\\n";
      return 0;
    }
    b += ends[i].second;
  }
  if (b == 0)
    cout << "Yes\\n";
  else
    cout << "No\\n";
}

Error: 0

Fixed submission:

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

const int inf = 1e9 + 33;

void chmin(int &x, int y) { // literally chmin(x, y) is similar to x = min(x, y)
  x = min(x, y);
}

signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  int n;
  cin >> n;
  vector<pair<int, int>> seqs(
      n); // sequences, sequence is a pair of minimal balance (balance is
          // count[(] - count[)] on prefix) and balance of the full string
  for (int w = 0; w < n; ++w) {
    string s;
    cin >> s;
    int cur_b = 0, min_b = inf; // current balance, minimal balance
    for (int i = 0; i < int(s.size()); ++i) {
      if (s[i] == '(')
        ++cur_b;
      else
        --cur_b;
      chmin(min_b, cur_b);
    }
    seqs[w] = make_pair(min_b, cur_b);
  }
  int b = 0; // balance of the answer
  multiset<pair<int, int>>
      bad_strings; // we would call a string bad if its minimal balance is more
                   // than our current balance
  multiset<pair<int, int>>
      god_strings; // we would call a string bad if its minimal balance is less
                   // than our current balance
  for (int i = 0; i < n; ++i)
    bad_strings.insert(seqs[i]);
  while (!bad_strings.empty() || !god_strings.empty()) {
    auto it = bad_strings.lower_bound(
        make_pair(-b, -inf)); // finding a string which minimal balance won't
                              // make our balance under 0 (making it negative is
                              // unacceptable in bracket sequence)
    vector<pair<int, int>> to_gods;
    for (auto jt = it; jt != bad_strings.end(); jt = next(jt))
      to_gods.push_back(*jt);
    for (auto pr : to_gods) {
      god_strings.insert(
          make_pair(pr.second,
                    pr.first)); // we care about balance more than about minimal
                                // balance because we know that its already in
                                // god tier so we swap first and second elements
      bad_strings.erase(pr);
    }
    if (god_strings.empty()) { // there are no strings found satisfying the
                               // condition of non negative balance
      cout << "No\\n";
      return 0;
    } else {
      auto jt = *prev(god_strings.end()); // best candidate which makes our
                                          // balance as big as possible
      if (jt.first >=
          0) { // if so, we safely remove him, even increasing our pool of
               // available god_strings by increasing our current balance
        b += jt.first;
        god_strings.erase(god_strings.find(
            jt)); // we remove only one entrance of jt to god tier, cuz they be
                  // some more strings with the same pair "seq"
      } else if (bad_strings.empty()) // if balance is less than 0 we can never
                                      // ever increase ourself, so, if bad is
                                      // not empty - we lose
        break; // we will work on that case in the other way after the cycle,
               // this case is 100% needed if our answer exists
      else {
        cout << "No\\n";
        return 0;
      }
    }
  }
  multiset<pair<int, int>> god_not_used,
      god_prior; // god seqs which werent added because their balance is
                 // negative
  for (auto pr : god_strings) {
    god_not_used.insert(make_pair(pr.second, pr.first));
    god_prior.insert(make_pair(pr.first, -pr.second));
  }
  while (!god_not_used.empty()) { // if answer exists they are not empty, else,
                                  // balance is more than 0
    if (god_not_used.begin()->first <
        -b) { // there exists some string that cant be reached without not
              // increasing(which is unreal) the ans
      cout << "No\\n";
      return 0;
    } else {
      auto jt = *prev(god_prior.end());
      b += jt.first;
      god_not_used.erase(god_not_used.find(make_pair(-jt.second, jt.first)));
      god_strings.erase(prev(god_strings.end()));
    }
  }
  if (b == 0) // bracket sequence balance is 0, in other way - its just a
              // string, not a bracket sequence
    cout << "Yes\\n";
  else
    cout << "No\\n";
}