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)

/*********************************************
* 20.05.22 AtCoder Beginner Contest 151
* 
*
*********************************************/

namespace TempName{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Text;
    using static System.Console;
    using static IOmacro.CSharpInput; 
    using static IOmacro.CppInput;
    using static IOmacro.CConst;

    public class CRun{
        public readonly char problem_num = 'C';
        
/*********************************************
A - Next Alphabet

z でない英小文字 Cが与えられます。アルファベット順で 
Cの次の文字を出力してください。
*********************************************/
public void solve_A() {
    string input = _string;
    char ans = (char)(input[0] + 1);
    WriteLine(ans);
}

/*********************************************
B - Achieve the Goal

A man is taking exams on N subjects.
The score on each subject will be an integer between 0 to K.
He has already taken N - 1 subjects, and scored A_i points on the i_th subject.
His goal is achieve the average score of M points or above on the N subjects.
Print the minimum number of points he needs on the final subject to achieve his goal.
If the goal is unachievable, print -1 instead.

input:
N K M
A1 , ... AN-1
*********************************************/
public void solve_B() {
    int N = cin;
    int K = cin;
    int M = cin;
    int[] A = _inta;
    
    int sum = 0;
    foreach (var ix in A) sum += ix;
    
    int goal = M * N;
    int need = goal - sum;
    if (need < 0) need = 0;
    if (need <= K) {
        WriteLine (need);
    }
    else {
        WriteLine("-1");
    }
}

/*********************************************
C - Welcome to AtCoder 

Ｎ問の問題
Ｍ回の提出
i番目の提出はp_i番目の問題への提出であり、結果は　'AC' または　'WA'
正解数は、'AC'を一回以上出した問題の数
ペナルティ数は、'AC'を一回以上だした問題において、ACまでの'WA'
正解数とペナルティ数は？

input:
N M
p1 S1
...
pM sM
*********************************************/
public void solve_C() {
    
    int problem_cnt = cin;
    int submit_cnt = cin;
    
    var submit = new Tuple<int, string>[submit_cnt];
    for (int ix = 0; ix < submit_cnt; ix++) {
        int p = cin;
        string s = cin;
        submit[ix] = Tuple.Create(p, s);
    }
    
    int ans_pass = 0;
    int ans_penalty = 0;
    int[] problem_WA = new int[problem_cnt + 2];
    Array.Clear(problem_WA, 0, problem_WA.Length);
    bool[] problem_chk = new bool[problem_cnt + 2];
    Array.Clear(problem_chk, 0, problem_chk.Length);
    
    for (int ix = 0; ix < submit_cnt; ix++) {
        int target_num = submit[ix].Item1 - 1;
        string target_result = submit[ix].Item2;
        
        if (target_result == "AC") {
            if (problem_chk[target_num] == false) {
                problem_chk[target_num] = true;
                ans_penalty += problem_WA[target_num];
                ans_pass += 1;
            }
        }
        else if (target_result == "WA") {
            problem_WA[target_num] += 1;
        }
        
    }
    
    WriteLine($"{ans_pass} {ans_penalty}");
}

/*********************************************

*********************************************/
public void solve_D() {
    
}

/*********************************************

*********************************************/
public void solve_E() {
    
}

/*********************************************

*********************************************/
public void solve_F() {
    
}

    }
    class Program { 
        static void Main() { 
            var run = new CRun();
            switch (run.problem_num) {
                case 'A': run.solve_A(); break;
                case 'B': run.solve_B(); break;
                case 'C': run.solve_C(); break;
                case 'D': run.solve_D(); break;
                case 'E': run.solve_E(); break;
                case 'F': run.solve_F(); break;
            }
        } 
    }
}

namespace IOmacro {
    //20.05.10. 수정
    
    using System; 
    using System.Linq; 
    using System.IO;
    using System.Collections.Generic;
    
    public class CSharpInput {
        public static StreamWriter _writer = new StreamWriter(Console.OpenStandardOutput());
        public const char separator = ' ';
        public static string _string{get{return Console.ReadLine();}}
        public static string[] _stringa{get{return (Console.ReadLine().Split(separator));}}
        public static int _int{get{return int.Parse(Console.ReadLine());}}
        public static int[] _inta{get{return Console.ReadLine().Split(separator).Select(int.Parse).ToArray();}}
        public static long _long{get{return long.Parse(Console.ReadLine());}}
        public static long[] _longa{get{return Console.ReadLine().Split(separator).Select(long.Parse).ToArray();}}    
        public static double _double{get{return double.Parse(Console.ReadLine());}}
        public static double[] _doublea{get{return Console.ReadLine().Split(separator).Select(double.Parse).ToArray();}}    
    }
    
    public class CConst {
        public static readonly int MINI = int.MaxValue;
        public static readonly long INF = Int64.MaxValue;
    }
    
    public class CppInput {
        public static CppInput cin => new CppInput();
        public const char separator = ' ';
        private static readonly Queue<string> _input = new Queue<string>();
        private CppInput(){}
        public static implicit operator string(CppInput _) {
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return _input.Dequeue();
        }
        public static implicit operator int(CppInput _){
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return int.Parse(_input.Dequeue());
        }
        public static implicit operator long(CppInput _){
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return long.Parse(_input.Dequeue());
        }
        public static implicit operator double(CppInput _){
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return double.Parse(_input.Dequeue());
        }
    }
    
    public static class EnumerableExtension {
        public delegate void Function<in T>(T val);
        public static void foreachExtension<T>(this IEnumerable<T> enumerable, Function<T> function) {
            foreach (var x in enumerable) function(x);
        }
    }
}