Problem p02686 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
string S[100000];

bool balanced(string s) {
  int opened = 0;
  for (int i = 0; i < s.size(); i++) {
    if (s[i] == '(') {
      opened++;
    } else if (s[i] == ')') {
      if (opened == 0) {
        return false;
      }
      opened--;
    }
  }
  if (opened != 0) {
    return false;
  }
  return true;
}

int right_open(string s) {
  int opened = 0;
  for (int i = 0; i < s.size(); i++) {
    if (s[i] == '(') {
      opened++;
    } else if (s[i] == ')') {
      if (opened > 0) {
        opened--;
      }
    }
  }
  return opened;
}

int left_open(string s) {
  int opened = 0;
  for (int i = s.size() - 1; i >= 0; i--) {
    if (s[i] == ')') {
      opened++;
    } else if (s[i] == '(') {
      if (opened > 0) {
        opened--;
      }
    }
  }
  return opened;
}

int main() {
  int N;
  cin >> N;
  for (int i = 0; i < N; i++) {
    cin >> S[i];
  }

  vector<int> right_opens;
  vector<int> left_opens;
  vector<pair<int, int>> both_opens_pos;
  vector<pair<int, int>> both_opens_neg;
  for (int i = 0; i < N; i++) {
    int right = right_open(S[i]);
    int left = left_open(S[i]);
    if (right == 0 && left == 0) {
      continue;
    }
    if (left == 0) {
      right_opens.push_back(right);
    } else if (right == 0) {
      left_opens.push_back(left);
    } else {
      if (right - left >= 0) {
        both_opens_pos.push_back(make_pair(left, right));
      } else {
        both_opens_neg.push_back(make_pair(left, right));
      }
    }
  }

  sort(both_opens_pos.begin(), both_opens_pos.end());
  sort(both_opens_neg.begin(), both_opens_neg.end());
  reverse(both_opens_neg.begin(), both_opens_neg.end());

  int cur_opens = 0;
  for (int i = 0; i < right_opens.size(); i++) {
    cur_opens += right_opens[i];
  }
  for (int i = 0; i < both_opens_pos.size(); i++) {
    cur_opens -= both_opens_pos[i].first;
    if (cur_opens < 0) {
      cout << "No" << endl;
      return 0;
    }
    cur_opens += both_opens_pos[i].second;
  }

  for (int i = 0; i < both_opens_neg.size(); i++) {
    cur_opens -= both_opens_neg[i].first;
    if (cur_opens < 0) {
      cout << "No" << endl;
      return 0;
    }
    cur_opens += both_opens_neg[i].second;
  }

  for (int i = 0; i < left_opens.size(); i++) {
    cur_opens -= left_opens[i];
  }

  if (cur_opens != 0) {
    cout << "No" << endl;
  } else {
    cout << "Yes" << endl;
  }

  return 0;
}


Fixed submission:
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
string S[1000000];

bool balanced(string s) {
  int opened = 0;
  for (int i = 0; i < s.size(); i++) {
    if (s[i] == '(') {
      opened++;
    } else if (s[i] == ')') {
      if (opened == 0) {
        return false;
      }
      opened--;
    }
  }
  if (opened != 0) {
    return false;
  }
  return true;
}

int right_open(string s) {
  int opened = 0;
  for (int i = 0; i < s.size(); i++) {
    if (s[i] == '(') {
      opened++;
    } else if (s[i] == ')') {
      if (opened > 0) {
        opened--;
      }
    }
  }
  return opened;
}

int left_open(string s) {
  int opened = 0;
  for (int i = s.size() - 1; i >= 0; i--) {
    if (s[i] == ')') {
      opened++;
    } else if (s[i] == '(') {
      if (opened > 0) {
        opened--;
      }
    }
  }
  return opened;
}

int main() {
  int N;
  cin >> N;
  for (int i = 0; i < N; i++) {
    cin >> S[i];
  }

  vector<int> right_opens;
  vector<int> left_opens;
  vector<pair<int, int>> both_opens_pos;
  vector<pair<int, int>> both_opens_neg;
  for (int i = 0; i < N; i++) {
    int right = right_open(S[i]);
    int left = left_open(S[i]);
    if (right == 0 && left == 0) {
      continue;
    }
    if (left == 0) {
      right_opens.push_back(right);
    } else if (right == 0) {
      left_opens.push_back(left);
    } else {
      if (right - left >= 0) {
        both_opens_pos.push_back(make_pair(left, right));
      } else {
        both_opens_neg.push_back(make_pair(left, right));
      }
    }
  }

  sort(both_opens_pos.begin(), both_opens_pos.end());
  sort(both_opens_neg.begin(), both_opens_neg.end());
  reverse(both_opens_neg.begin(), both_opens_neg.end());

  int cur_opens = 0;
  for (int i = 0; i < right_opens.size(); i++) {
    cur_opens += right_opens[i];
  }
  for (int i = 0; i < both_opens_pos.size(); i++) {
    cur_opens -= both_opens_pos[i].first;
    if (cur_opens < 0) {
      cout << "No" << endl;
      return 0;
    }
    cur_opens += both_opens_pos[i].second;
  }

  for (int i = 0; i < both_opens_neg.size(); i++) {
    cur_opens -= both_opens_neg[i].first;
    if (cur_opens < 0) {
      cout << "No" << endl;
      return 0;
    }
    cur_opens += both_opens_neg[i].second;
  }

  for (int i = 0; i < left_opens.size(); i++) {
    cur_opens -= left_opens[i];
  }

  if (cur_opens != 0) {
    cout << "No" << endl;
  } else {
    cout << "Yes" << endl;
  }

  return 0;
}