Problem:
Score : 600 points

Problem Statement

There is a game that involves three variables, denoted A, B, and C.

As the game progresses, there will be N events where you are asked to make a choice.
Each of these choices is represented by a string s_i. If s_i is AB, you must add 1 to A or B then subtract 1 from the other; if s_i is AC, you must add 1 to A or C then subtract 1 from the other; if s_i is BC, you must add 1 to B or C then subtract 1 from the other.

After each choice, none of A, B, and C should be negative.

Determine whether it is possible to make N choices under this condition. If it is possible, also give one such way to make the choices.

Constraints

1 \leq N \leq 10^5

0 \leq A,B,C \leq 10^9

N, A, B, C are integers.

s_i is AB, AC, or BC.

Input

Input is given from Standard Input in the following format:

N A B C
s_1
s_2
:
s_N

Output

If it is possible to make N choices under the condition, print Yes; otherwise, print No.

Also, in the former case, show one such way to make the choices in the subsequent N lines. The (i+1)-th line should contain the name of the variable (A, B, or C) to which you add 1 in the i-th choice.

Sample Input 1

2 1 3 0
AB
AC

Sample Output 1

Yes
A
C

You can successfully make two choices, as follows:

In the first choice, add 1 to A and subtract 1 from B. A becomes 2, and B becomes 2.

In the second choice, add 1 to C and subtract 1 from A. C becomes 1, and A becomes 1.

Sample Input 2

3 1 0 0
AB
BC
AB

Sample Output 2

No

Sample Input 3

1 0 9 0
AC

Sample Output 3

No

Sample Input 4

8 6 9 1
AC
BC
AB
BC
AC
BC
AB
AB

Sample Output 4

Yes
C
B
B
C
C
B
A
A

Solution in C# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

public class ABC166_F
{

    public static void Main()
    {
        InLineArg(out long[] ls);
        int n = (int)ls[0];
        long a = ls[1], b = ls[2], c = ls[3];
        bool can = true;
        var list = new List<string>();
        for(int i = 0;i < n; i++)
        {
            InLine(out string s);
            if(s == "AB")
            {
                var d = Max(new double[] { a, b }, 1)[0];
                if (d <= 0) can = false;
                else if (a == d)
                {
                    list.Add("B");
                    b++;
                    a--;
                }
                else if (b == d)
                {
                    list.Add("A");
                    a++;
                    b--;
                }
            }
            else if (s == "AC")
            {
                var d = Max(new double[] { a, c }, 1)[0];
                if (d <= 0) can = false;
                else if (a == d)
                {
                    list.Add("C");
                    c++;
                    a--;
                }
                else if (c == d)
                {
                    list.Add("A");
                    a++;
                    c--;
                }
            }
            else if (s == "BC")
            {
                var d = Max(new double[] { b, c }, 1)[0];
                if (d <= 0) can = false;
                else if (b == d)
                {
                    list.Add("C");
                    c++;
                    b--;
                }
                else if (c == d)
                {
                    list.Add("B");
                    b++;
                    c--;
                }
            }

            if(can == false)
            {
                OutNo();
                return;
            }
        }
        OutYes();
        foreach (var r in list) Out(r);
    }

    /* Template */
    private static object[] nullobj = null;
    public static int len = -1;
    public static int count = -1;
    public static double result = 0;
    public static string line = "";

    //文字コード変換
    public static int ConvertInt(char c)
    {
        return c;
    }

    //配列入力:1入力
    public static A[] InArgs<A>(int count)
    {
        InArgs(count, out A[] var, out nullobj, out nullobj, 1);
        return var;
    }

    //配列入力:1入力
    public static void InArgs<A>(int count, out A[] var)
    {
        InArgs(count, out var, out nullobj, out nullobj, 1);
    }

    //配列入力:2入力
    public static void InArgs<A, B>(int count, out A[] var1, out B[] var2)
    {
        InArgs(count, out var1, out var2, out nullobj, 2);
    }

    //配列入力:3入力
    public static void InArgs<A, B, C>(int count, out A[] var1, out B[] var2, out C[] var3)
    {
        InArgs(count, out var1, out var2, out var3, 3);
    }

    //配列入力:内部処理
    private static void InArgs<A, B, C>(int count, out A[] var1, out B[] var2, out C[] var3, int ci)
    {
        var1 = new A[count];
        var2 = new B[count];
        var3 = new C[count];
        for (int i = 0; i < count; i++)
        {
            InLine(out var1[i], out var2[i], out var3[i], ci);
        }
    }

    //入力:1入力
    public static A InLine<A>()
    {
        InLine(out A var);
        return var;
    }

    //入力:1入力
    public static void InLine<A>(out A var)
    {
        InLine(out var, out nullobj, out nullobj, 1);
    }

    //入力:2入力
    public static void InLine<A, B>(out A var1, out B var2)
    {
        InLine(out var1, out var2, out nullobj, 2);
    }

    //入力:3入力
    public static void InLine<A, B, C>(out A var1, out B var2, out C var3)
    {
        InLine(out var1, out var2, out var3, 3);
    }

    //入力:内部処理
    public static void InLine<A, B, C>(out A var1, out B var2, out C var3, int c)
    {
        var2 = default;
        var3 = default;
        object[] o = new object[c];
        Type[] t = new Type[] { typeof(A), typeof(B), typeof(C) };

        var line = Console.ReadLine();
        string[] s;
        if (o.Length == 1) s = new string[1] { line };
        else s = line.Split(' ');
        for (int i = 0; i < s.Length; i++)
        {
            if (typeof(int) == t[i]) o[i] = int.Parse(s[i]);
            else if (typeof(long) == t[i]) o[i] = long.Parse(s[i]);
            else if (typeof(double) == t[i]) o[i] = double.Parse(s[i]);
            else o[i] = s[i];
        }
        var1 = (A)o[0];
        if (c == 2) var2 = (B)o[1];
        if (c == 3) var3 = (C)o[2];
    }

    //入力:1行配列
    public static A[] InLineArg<A>()
    {
        InLineArg(out A[] var);
        return var;
    }

    //入力:1行配列
    public static void InLineArg<A>(out A[] arg)
    {
        object obj = null;
        Type t = typeof(A);
        string[] line = Console.ReadLine().Split(' ');
        if (typeof(int) == t) obj = line.Select(int.Parse).ToArray();
        else if (typeof(long) == t) obj = line.Select(long.Parse).ToArray();
        else if (typeof(double) == t) obj = line.Select(double.Parse).ToArray();
        else obj = line;
        arg = (A[])obj;
    }

    //文字列結合
    public static string JoinString(object obj, string sep)
    {
        return obj.GetType().IsArray ?
            string.Join(sep, ((IEnumerable<object>)obj).Select(i => i.ToString()).ToArray()) : obj.ToString();
    }

    //出力
    public static void Out(object o)
    {
        Console.WriteLine(o);
    }

    //出力:変数result
    public static void OutResult()
    {
        Console.WriteLine(result);
    }

    //出力:Yes
    public static void OutYes()
    {
        Console.WriteLine("Yes");
    }

    //出力:No
    public static void OutNo()
    {
        Console.WriteLine("No");
    }

    //出力:YES
    public static void OutYES()
    {
        Console.WriteLine("YES");
    }

    //出力:NO
    public static void OutNO()
    {
        Console.WriteLine("NO");
    }

    //辞書生成
    private static Dictionary<A, B> PutDict<A, B>(A[] key, B[] value)
    {
        if (key.Length != value.Length) return null;
        var dic = new Dictionary<A, B>();
        for (int i = 0; i < Math.Min(key.Length, value.Length); i++)
        {
            if (!dic.ContainsKey(key[i])) dic.Add(key[i], value[i]);
            else dic[key[i]] = value[i];
        }
        return dic;
    }

    //最大
    public static double[] Max(double[] array, int count)
    {
        double[] result = new double[count];
        for (int c = 0; c < count; c++)
        {
            double max = -1;
            var plus = Vector<double>.Count;
            var vmax = new Vector<double>(max);
            for (int i = 0; i < array.Length - plus; i += plus)
            {
                vmax = Vector.Max(vmax, new Vector<double>(array, i));
            }
            for (int i = 0; i < plus; i++)
            {
                if (max < vmax[i]) max = vmax[i];
            }
            for (int i = array.Length - plus; i < array.Length; i++)
            {
                if (i < 0) i = 0;
                if (max < array[i]) max = array[i];
            }

            result[c] = max;
            if (c != count - 1)
            {
                var list = new List<double>(array);
                list.Remove(max);
                array = list.ToArray();
            }
        }
        return result;
    }

    //最小
    public static double[] Min(double[] array, int count)
    {
        double[] result = new double[count];
        for (int c = 0; c < count; c++)
        {
            double min = double.MaxValue;
            var plus = Vector<double>.Count;
            var vmax = new Vector<double>(min);
            for (int i = 0; i < array.Length - plus; i += plus)
            {
                vmax = Vector.Min(vmax, new Vector<double>(array, i));
            }
            for (int i = 0; i < plus; i++)
            {
                if (min > vmax[i]) min = vmax[i];
            }
            for (int i = array.Length - plus; i < array.Length; i++)
            {
                if (i < 0) i = 0;
                if (min > array[i]) min = array[i];
            }

            result[c] = min;
            if (c != count - 1)
            {
                var list = new List<double>(array);
                list.Remove(min);
                array = list.ToArray();
            }
        }
        return result;
    }

    //公約数
    public static int[] CommonDivisor(int num)
    {
        return CommonDivisor((double)num).Select(i => (int)i).ToArray();
    }

    public static double[] CommonDivisor(double num)
    {
        double l = 2, n = num;
        double[] result = new double[0];

        while (l * l <= num)
        {
            if (n % l == 0)
            {
                n /= l;
                Array.Resize(ref result, result.Length + 1);
                result[^1] = l;
            }
            else l++;
        }
        if (n != 1)
        {
            Array.Resize(ref result, result.Length + 1);
            result[^1] = n;
        }
        return result;
    }

    //大小比較
    public static bool Compare(bool lequal, double a, double x, double b, bool requal)
    {
        if (a <= x && x <= b)
        {
            if ((!lequal && x == a) || (!requal && x == b)) return false;
            else return true;
        }
        return false;
    }

    //互いに素
    public static bool IsRelativelyPrime(double a, double b)
    {
        return a > 1 && b > 1 ? CommonDivisor(a).Intersect(CommonDivisor(b)).ToArray().Length == 0 : false;
    }

    //素数判定
    public static bool IsPrimeNumber(int num)
    {
        if (num < 2) return false;
        else if (num == 2) return true;
        else if (num % 2 == 0) return false;

        double sqrtNum = Math.Sqrt(num);
        for (int i = 3; i <= sqrtNum; i += 2)
        {
            if (num % i == 0) return false;
        }
        return true;
    }

    //最大公約数
    public static int GCD(int a, int b)
    {
        return (int)GCD((double)a, b);
    }

    public static double GCD(double a, double b)
    {
        double[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        Dictionary<double, int> dic1 = new Dictionary<double, int>(), dic2 = new Dictionary<double, int>();
        int count = 0;
        double n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic1.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic1.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
        foreach (double l in dic2.Keys)
        {
            result *= Math.Pow(l, dic2[l]);
        }
        return result;
    }

    //最小公倍数
    public static double LCM(double a, double b)
    {
        double[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        var dic = new Dictionary<double, int>();
        int count = 0;
        double n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
                else if (n != 0) dic.Add(n, count);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
        else dic.Add(n, count);
        foreach (double l in dic.Keys)
            result *= (double)Math.Pow(l, dic[l]);
        return result;
    }

    //組合せ数(nCr)
    public static double Combination(int n, int r)
    {
        if (n / 2 < r) r = n - r;
        return TotalPower(n, r + 1) / TotalPower(n - r);
    }

    //組合せ数総和(Σ(k=1,n,nCk))
    public static double CombinationSum(int n)
    {
        return Math.Pow(2, n);
    }

    //重複組合せ数(nHr)
    public static double RepetitionCombination(int n, int r)
    {
        return Combination(n + r - 1, r);
    }

    //重複組合せ数総和(Σ(k=1,n,nHk))
    public static double RepetitionCombinationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionCombination(n, i);
        }
        return result;
    }

    //順列数(nPr)
    public static double Permutation(int n, int r)
    {
        return TotalPower(n, r + 1);
    }

    //順列数総和(Σ(k=1,n,nPk))
    public static double PermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += Permutation(n, i);
        }
        return result;
    }

    //円順列数
    public static double CircularPermutation(int n)
    {
        return TotalPower(n - 1);
    }

    //円順列数総和
    public static double CircularPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += CircularPermutation(i);
        }
        return result;
    }



    //数珠順列数
    public static double NecklacePermutation(int n)
    {
        return CircularPermutation(n - 1) / 2;
    }

    //数珠順列数総和
    public static double NecklacePermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += NecklacePermutation(i);
        }
        return result;
    }

    //重複順列数(nΠr)
    public static double RepetitionPermutation(int n, int r)
    {
        return Math.Pow(n, r);
    }

    //重複順列数総和(Σ(k=1,n,nΠk))
    public static double RepetitionPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionPermutation(n, i);
        }
        return result;
    }

    //総乗
    public static double TotalPower(int max)
    {
        return TotalPower(max, 1);
    }

    public static double TotalPower(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result *= i;
        return result;
    }

    public static double TotalPower(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result *= i;
        return result;
    }

    //総和
    public static double TotalSum(int max)
    {
        return TotalSum(max, 1);
    }

    public static double TotalSum(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result += i;
        return result;
    }

    public static double TotalSum(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result += i;
        return result;
    }
}