Problem:
Score : 300 points

Problem Statement

Takahashi participated in a contest on AtCoder.

The contest had N problems.

Takahashi made M submissions during the contest.

The i-th submission was made for the p_i-th problem and received the verdict S_i (AC or WA).

The number of Takahashi's correct answers is the number of problems on which he received an AC once or more.

The number of Takahashi's penalties is the sum of the following count for the problems on which he received an AC once or more: the number of WAs received before receiving an AC for the first time on that problem.

Find the numbers of Takahashi's correct answers and penalties.

Constraints

N, M, and p_i are integers.

1 \leq N \leq 10^5

0 \leq M \leq 10^5

1 \leq p_i \leq N

S_i is AC or WA.

Input

Input is given from Standard Input in the following format:

N M
p_1 S_1
:
p_M S_M

Output

Print the number of Takahashi's correct answers and the number of Takahashi's penalties.

Sample Input 1

2 5
1 WA
1 AC
2 WA
2 AC
2 WA

Sample Output 1

2 2

In his second submission, he received an AC on the first problem for the first time. Before this, he received one WA on this problem.

In his fourth submission, he received an AC on the second problem for the first time. Before this, he received one WA on this problem.

Thus, he has two correct answers and two penalties.

Sample Input 2

100000 3
7777 AC
7777 AC
7777 AC

Sample Output 2

1 0

Note that it is pointless to get an AC more than once on the same problem.

Sample Input 3

6 0

Sample Output 3

0 0

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

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

namespace Contest
{
    partial class Program
    {
        static void Main(string[] args)
        {
            ABC151C();
        }

        static void ABC151A()
        {
            var s = ReadStr();
            Console.WriteLine((char)(s[0] + 1));
        }
        static void ABC151B()
        {
            var nkm = ReadIntN();
            var A = ReadIntN();
            var N = nkm[0];
            var K = nkm[1];
            var M = nkm[2];
            var goal = N * M - A.Sum();
            Console.WriteLine(goal > K ? -1 : (goal < 0 ? 0 : goal));
        }
        static void ABC151C()
        {
            var nm = ReadIntN();
            var PS = ReadTupleStr(nm[1]);
            var N = nm[0];
            int[] ac = new int[N + 1];
            int[] wa = new int[N + 1];
            foreach(var ps in PS)
            {
                var n = Convert.ToInt32(ps.Item1);
                if (ps.Item2 == "AC")
                {
                    ac[n] = 1;
                }
                else
                {
                    if (ac[n] == 0) { wa[n]++; }
                }
            }
            long countAC = ac.Sum();
            long countWA = Enumerable.Range(0, ac.Length).Select(i => ac[i] > 0 ? wa[i] : 0).Sum();
            Console.WriteLine("{0} {1}", countAC, countWA);
        }
        static void ABC151D()
        {
            var hw = ReadIntN();
            var H = hw[0];
            var W = hw[1];
            bool[,] road = new bool[H + 2, W + 2];
            for (int h = 0; h < H; ++h)
            {
                var str = ReadStr();
                for (int w = 0; w < W; ++w)
                {
                    road[h + 1, w + 1] = str[w] == '.';
                }
            }
            Tuple<int, int>[] moves = new Tuple<int, int>[] { new Tuple<int, int>(-1, 0), new Tuple<int, int>(1, 0), new Tuple<int, int>(0, -1), new Tuple<int, int>(0, 1) };
            int max = 0;
            for(int startH = 1; startH <= H; ++startH)
            {
                for(int startW = 1; startW <= W; ++startW)
                {
                    bool[,] done = new bool[H + 2, W + 2];
                    List<Tuple<int,int>> list = new List<Tuple<int, int>>();
                    done[startH, startW] = true;
                    list.Add(new Tuple<int, int>(startH, startW));
                    int counter = -1;
                    while (list.Count > 0)
                    {
                        List<Tuple<int, int>> next = new List<Tuple<int, int>>();
                        foreach (var t in list)
                        {
                            foreach(var move in moves)
                            {
                                var h = t.Item1 + move.Item1;
                                var w = t.Item2 + move.Item2;
                                if(!done[h,w] && road[h, w])
                                {
                                    done[h, w] = true;
                                    next.Add(new Tuple<int, int>(h, w));
                                }
                            }
                        }
                        list = next;
                        counter++;
                    }
                    max = Math.Max(max, counter);
                }
            }
            Console.WriteLine(max);
        }
        static void ABC151E()
        {
            var nk = ReadIntN();
            var A = ReadLongN();
            var N = nk[0];
            var K = nk[1];
            A = A.OrderBy(x => x).ToArray();
            var combFunc = Util.Combin(N, Util.P);
            long sumMax = 0;
            long sumMin = 0;
            for(int i = 0; i < N; ++i)
            {
                sumMax = (sumMax + combFunc(i, K - 1) * A[i]) % Util.P;
                sumMin = (sumMin + combFunc(N - i - 1, K - 1) * A[i]) % Util.P;
            }
            Console.WriteLine((sumMax - sumMin + Util.P * 10) % Util.P);
        }
        static void ABC151F()
        {
            var N = ReadInt();
            var XY = ReadTupleDouble(N);
            double eps = 0.000001;

            double min = Double.MaxValue;

            /// 2点間の距離
            Func<Tuple<double, double>, Tuple<double, double>, double> distance = (a, b) =>
            {
                var diff1 = a.Item1 - b.Item1;
                var diff2 = a.Item2 - b.Item2;
                return Math.Sqrt(diff1 * diff1 + diff2 * diff2);
            };

            /// 最小の半径を与える円は以下のいずれか
            /// (1) ある2点を直径とする
            /// (2) ある3点を通る

            /// ある2点を直径とする
            for (int i = 0; i < N; ++i)
            {
                for(int j = i + 1; j < N; ++j)
                {
                    var p = XY[i];
                    var q = XY[j];

                    ///中心o 半径r
                    var o = new Tuple<double, double>((p.Item1 + q.Item1) / 2, (p.Item2 + q.Item2) / 2);
                    var r = distance(p, o);

                    /// 全点がoからr以内にあればOK
                    bool ok = true;
                    for(int k = 0; k < N; ++k)
                    {
                        if(distance(XY[k], o) > r + eps)
                        {
                            ok = false;
                            break;
                        }
                    }
                    if (ok)
                    {
                        min = Math.Min(min, r);
                    }
                }
            }

            /// ある3点を通る
            for (int i = 0; i < N; ++i)
            {
                var I = XY[i];
                for (int j = i + 1; j < N; ++j)
                {
                    var J = XY[j];
                    /// 線分(I,J)の垂直二等分線 a1 x + b1 y + c1 =0
                    var a1 = J.Item1 - I.Item1;
                    var b1 = J.Item2 - I.Item2;
                    var c1 = -a1 * (I.Item1 + J.Item1) / 2 - b1 * (I.Item2 + J.Item2) / 2;
                    for (int k = j + 1; k < N; ++k)
                    {
                        var K = XY[k];
                        /// 線分(I,K)の垂直二等分線 a2 x + b2 y + c2 =0
                        var a2 = K.Item1 - I.Item1;
                        var b2 = K.Item2 - I.Item2;
                        var c2 = -a2 * (I.Item1 + K.Item1) / 2 - b2 * (I.Item2 + K.Item2) / 2;

                        /// 垂直二等分線が平行＝3点が同一直線上にあるので円は存在しない
                        var a1b2a2b1 = a1 * b2 - a2 * b1;
                        if (Math.Abs(a1b2a2b1) < eps)
                        {
                            continue;
                        }

                        /// 垂直二等分線の交点が円の中心
                        var ox = (c2 * b1 - c1 * b2) / a1b2a2b1;
                        var oy = -(c2 * a1 - c1 * a1) / a1b2a2b1;
                        var o = new Tuple<double, double>(ox, oy);
                        var r = distance(o, I);

                        /// 全点がoからr以内にあればOK
                        bool ok = true;
                        for (int l = 0; l < N; ++l)
                        {
                            if (distance(XY[l], o) > r + eps)
                            {
                                ok = false;
                                break;
                            }
                        }
                        if (ok)
                        {
                            min = Math.Min(min, r);
                        }
                    }
                }
            }
            Console.WriteLine(min);
        }


        class Util
        {
            public static readonly long P = 1000000007;

            public static Dictionary<long,int> Factorize(long x)
            {
                var dict = new Dictionary<long, int>();
                long minp = 2;
                while (x > 1)
                {
                    bool ok = false;
                    for(long p = minp; p * p <= x; ++p)
                    {
                        if (x % p == 0)
                        {
                            if (!dict.ContainsKey(p))
                            {
                                dict.Add(p, 0);
                            }
                            dict[p]++;
                            minp = p;
                            x /= p;
                            ok = true;
                            break;
                        }
                    }
                    if (!ok)
                    {
                        if (!dict.ContainsKey(x)) { dict.Add(x, 0); }
                        dict[x]++;
                        break;
                    }
                }
                return dict;
            }
            public static long Inverse(long a, long p)
            {
                long b = p, c = 1, d = 0, e = 0, f = 0;
                while (b != 0)
                {
                    e = a / b;
                    f = b; b = a - e * b; a = f;
                    f = d; d = c - e * d; c = f;
                }
                c %= p;
                return c + (c < 0 ? p : 0);
            }
            public static long[] Facts(int n, long p)
            {
                var facts = new long[n + 1];
                facts[0] = 1;
                for (int i = 1; i <= n; ++i)
                {
                    facts[i] = (i * facts[i - 1]) % p;
                }
                return facts;
            }
            public static Func<int,int,long> Combin(int n, long P)
            {
                var fact = Facts(n, P);
                var inv = fact.Select(x => Inverse(x, P)).ToArray();
                return (N, M) =>
                {
                    if (N < 0 || N < M || M < 0) { return 0; }
                    return (((fact[N] * inv[M]) % P) * inv[N - M]) % P;
                };
            }
        }

        static string ReadStr()
        {
            return Console.ReadLine();
        }
        static string[] ReadStrN()
        {
            return Console.ReadLine().Split(' ');
        }
        static int ReadInt()
        {
            return Convert.ToInt32(Console.ReadLine());
        }
        static int[] ReadIntN()
        {
            return Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray();
        }
        static long ReadLong()
        {
            return Convert.ToInt64(Console.ReadLine());
        }
        static long[] ReadLongN()
        {
            return Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray();
        }
        static Tuple<string, string>[] ReadTupleStr(int n)
        {
            List<Tuple<string, string>> list = new List<Tuple<string, string>>();
            for (int i = 0; i < n; ++i)
            {
                var ab = ReadStrN();
                list.Add(new Tuple<string, string>(ab[0], ab[1]));
            }
            return list.ToArray();
        }
        static Tuple<long, long>[] ReadTupleLong(int n)
        {
            List<Tuple<long, long>> list = new List<Tuple<long, long>>();
            for (int i = 0; i < n; ++i)
            {
                var ab = ReadLongN();
                list.Add(new Tuple<long, long>(ab[0], ab[1]));
            }
            return list.ToArray();
        }
        static Tuple<double, double>[] ReadTupleDouble(int n)
        {
            List<Tuple<double, double>> list = new List<Tuple<double, double>>();
            for (int i = 0; i < n; ++i)
            {
                var ab = ReadLongN();
                list.Add(new Tuple<double, double>(ab[0], ab[1]));
            }
            return list.ToArray();
        }
    }
}