Problem p02692 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
#define int int64
#define rep(i, n) for (int i = 0; i < n; i++)
#define FOR(i, a, b) for (int i = a; i < b; i++)
#define SORT(x) sort(x.begin(), x.end())
#define GSORT(x) sort(x.begin(), x.end(), greater<int>())
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define ALL(x) x.begin(), x.end()
#define V(T) vector<T>
typedef pair<int, int> P;
typedef pair<P, P> PP;
typedef vector<int> vi;
typedef vector<vi> vvi;
int max(int a, int b) {
  if (b > a)
    return b;
  else
    return a;
}
int min(int a, int b) {
  if (b < a)
    return b;
  else
    return a;
}
const int INF = 1e18;

signed main() {
  int N, A, B, C;
  vi abc(3);
  cin >> N;
  int sum = 0;
  rep(i, 3) {
    cin >> abc[i];
    sum += abc[i];
  }
  V(P) S(N);
  rep(i, N) {
    string s;
    cin >> s;
    S[i] = P(s[0] - 'A', s[1] - 'A');
  }

  vi res;

  // A+B+Cの合計で場合分け
  // 合計が0なら明らかに不可
  if (sum == 0) {
    cout << "No" << endl;

    // 合計が1なら、解は1通りしか存在しない
  } else if (sum == 1) {
    rep(i, N) {
      if (abc[S[i].fi] == 0 && abc[S[i].se] == 0) {
        cout << "No" << endl;
        return 0;
      } else {
        if (abc[S[i].fi]) {
          res.pb(S[i].se);
          abc[S[i].fi]--;
          abc[S[i].se]++;
        } else {
          res.pb(S[i].fi);
          abc[S[i].fi]++;
          abc[S[i].se]--;
        }
      }
    }

    // 合計が2以上なら、現在の状態とクエリでさらに場合分け
  } else {
    rep(i, N) {
      // クエリの文字の数が両方とも0なら、その時点で不可
      if (abc[S[i].fi] == 0 && abc[S[i].se] == 0) {
        cout << "No" << endl;
        return 0;
      }
      // クエリの文字の数のうちどちらか一方が0なら、そちらに足す
      else if (abc[S[i].fi] == 0 || abc[S[i].se] == 0) {
        if (abc[S[i].fi]) {
          res.pb(S[i].se);
          abc[S[i].fi]--;
          abc[S[i].se]++;
        } else {
          res.pb(S[i].fi);
          abc[S[i].fi]++;
          abc[S[i].se]--;
        }
        // クエリの文字の数が両方とも正なら、次のクエリを見て判定する
        // 次のクエリに含まれている文字のほうに足せば最適
        // 次のクエリと現在のクエリが同じなら、好きなほうに足せばよい
      } else {
        if (i < N - 1) {
          P np = S[i + 1];
          if (S[i].fi == np.fi || S[i].fi == np.se) {
            res.pb(S[i].fi);
            abc[S[i].fi]++;
            abc[S[i].se]--;
          } else {
            res.pb(S[i].se);
            abc[S[i].fi]--;
            abc[S[i].se]++;
          }
        } else {
          res.pb(S[i].fi);
        }
      }
    }
  }

  cout << "Yes" << endl;
  rep(i, N) cout << char(res[i] + 'A') << endl;

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
#define int int64
#define rep(i, n) for (int i = 0; i < n; i++)
#define FOR(i, a, b) for (int i = a; i < b; i++)
#define SORT(x) sort(x.begin(), x.end())
#define GSORT(x) sort(x.begin(), x.end(), greater<int>())
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define ALL(x) x.begin(), x.end()
#define V(T) vector<T>
typedef pair<int, int> P;
typedef pair<P, P> PP;
typedef vector<int> vi;
typedef vector<vi> vvi;
int max(int a, int b) {
  if (b > a)
    return b;
  else
    return a;
}
int min(int a, int b) {
  if (b < a)
    return b;
  else
    return a;
}
const int INF = 1e18;

signed main() {
  int N, A, B, C;
  vi abc(3);
  cin >> N;
  int sum = 0;
  rep(i, 3) {
    cin >> abc[i];
    sum += abc[i];
  }
  V(P) S(N);
  rep(i, N) {
    string s;
    cin >> s;
    S[i] = P(s[0] - 'A', s[1] - 'A');
  }

  vi res;

  // A+B+Cの合計で場合分け
  // 合計が0なら明らかに不可
  if (sum == 0) {
    cout << "No" << endl;
    return 0;
    // 合計が1なら、解は1通りしか存在しない
  } else if (sum == 1) {
    rep(i, N) {
      if (abc[S[i].fi] == 0 && abc[S[i].se] == 0) {
        cout << "No" << endl;
        return 0;
      } else {
        if (abc[S[i].fi]) {
          res.pb(S[i].se);
          abc[S[i].fi]--;
          abc[S[i].se]++;
        } else {
          res.pb(S[i].fi);
          abc[S[i].fi]++;
          abc[S[i].se]--;
        }
      }
    }

    // 合計が2以上なら、現在の状態とクエリでさらに場合分け
  } else {
    rep(i, N) {
      // クエリの文字の数が両方とも0なら、その時点で不可
      if (abc[S[i].fi] == 0 && abc[S[i].se] == 0) {
        cout << "No" << endl;
        return 0;
      }
      // クエリの文字の数のうちどちらか一方が0なら、そちらに足す
      else if (abc[S[i].fi] == 0 || abc[S[i].se] == 0) {
        if (abc[S[i].fi]) {
          res.pb(S[i].se);
          abc[S[i].fi]--;
          abc[S[i].se]++;
        } else {
          res.pb(S[i].fi);
          abc[S[i].fi]++;
          abc[S[i].se]--;
        }
        // クエリの文字の数が両方とも正なら、次のクエリを見て判定する
        // 次のクエリに含まれている文字のほうに足せば最適
        // 次のクエリと現在のクエリが同じなら、好きなほうに足せばよい
      } else {
        if (i < N - 1) {
          P np = S[i + 1];
          if (S[i].fi == np.fi || S[i].fi == np.se) {
            res.pb(S[i].fi);
            abc[S[i].fi]++;
            abc[S[i].se]--;
          } else {
            res.pb(S[i].se);
            abc[S[i].fi]--;
            abc[S[i].se]++;
          }
        } else {
          res.pb(S[i].fi);
        }
      }
    }
  }

  cout << "Yes" << endl;
  rep(i, N) cout << char(res[i] + 'A') << endl;

  return 0;
}