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;
using System.IO;

namespace AtCoder
{
	class Program
	{
		public static void Main()
		{
#if TextInput
			using(var reader = new StreamReader(Debug.SampleTextPath)) 
			{
				Console.SetIn(reader);
#endif
				var intArray = IO.ReadIntArray();
				int N = intArray[0] , M = intArray[1];
				var countStates = new int[N];
				var acCount = 0;
				var waCount = 0;
				for(var iIndex = 0 ; iIndex < M ; ++ iIndex)
				{
					var submission = IO.ReadArray();
					var checkIndex = int.Parse(submission[0]) - 1;
					if(countStates[checkIndex] != -1)
					{
						if(submission[1] == "AC")
						{
							++ acCount;
							waCount += countStates[checkIndex];
							countStates[checkIndex] = -1;
						}
						else
						{
							++ countStates[checkIndex];
						}
					}
				}
				IO.Write(new[] { acCount , waCount });
#if TextInput
			}
#endif
		}
	}

	public static class IO
	{
		public static string   Read()								 { return Console.ReadLine(); }
		public static string[] ReadArray(char iSplitter = ' ')		 { return Read().Split(iSplitter); }
		public static int	   ReadInt()							 { return int.Parse(Read()); }
		public static int[]	   ReadIntArray(char iSplitter = ' ')	 { return ReadArray().Select(iText => int.Parse(iText)).ToArray(); }
		public static long	   ReadLong()							 { return long.Parse(Read()); }
		public static long[]   ReadLongArray(char iSplitter = ' ')	 { return ReadArray().Select(iText => long.Parse(iText)).ToArray(); }
		public static double   ReadDouble()							 { return double.Parse(Read()); }
		public static double[] ReadDoubleArray(char iSplitter = ' ') { return ReadArray().Select(iText => double.Parse(iText)).ToArray(); }
		public static char	   ReadChar()							 { return Read()[0]; }
		public static char[]   ReadCharArray()						 { return Read().ToCharArray(); }

		public static void Write(string iValue)	 { Console.WriteLine(iValue); }
		public static void Write(int iValue)	 { Console.WriteLine(iValue); }
		public static void Write(long iValue)	 { Console.WriteLine(iValue); }
		public static void Write(double iValue)  { Console.WriteLine(iValue); }
		public static void Write(char iValue)	 { Console.WriteLine(iValue); }
		public static void Write(decimal iValue) { Console.WriteLine(iValue); }
		public static void Write(bool iValue)	 { Console.WriteLine(iValue ? "Yes" : "No"); }
		public static void Write<Type>(IEnumerable<Type> iValue , string iJoinWord = " ") { Console.WriteLine(string.Join(iJoinWord , iValue)); }
	}

	public static class Util
	{
		public static long Gcd(long i0 , long i1) { return (i0 > i1) ? _Gcd(i0 , i1) : _Gcd(i1 , i0); }
		public static long Lcm(long i0 , long i1) { return (i0 * i1) / Gcd(i0 , i1); }
		public static long ModPow(long iBaseNumber , long iPow , long iModNumber)
		{
			var num = 1L;
			while(iPow != 0)
			{
				if((iPow & 0x1) != 0)
				{
					num = (num * iBaseNumber) % iModNumber;
				}
				iBaseNumber = (iBaseNumber * iBaseNumber) % iModNumber;
				iPow >>= 1;
			}
			return num;
		}
		public static long CombinationNum(int iLeftNumber , int iRightNumber)
		{
			if(iRightNumber == 0) { return 1; }
			if(iLeftNumber == 0)  { return 0; }
			return iLeftNumber * CombinationNum(iLeftNumber - 1 , iRightNumber - 1) / iRightNumber;
		}
		public static long Factorial(long iNumber)
		{
			if(iNumber == 0) { return 1L; }
			return iNumber * Factorial(iNumber - 1);
		}
		private static long _Gcd(long i0 , long i1)	{ return (i1 == 0) ? i0 : _Gcd(i1 , i0 % i1); }
		private static int[] _indexBuf;
	}

	public class UnionFind
	{
		public int[] Parents;
		public int[] RootNums;
		public UnionFind(int iRootNum)
		{
			Parents = Enumerable.Range(0 , iRootNum).ToArray();
			RootNums = new int[iRootNum];
		}
		public void Normalize()
		{
			for(var iIndex = 0 ; iIndex < Parents.Length ; ++ iIndex)
			{
				var rootIndex = _GetRoot(iIndex);
				++ RootNums[rootIndex];
				Parents[iIndex] = rootIndex;
			}
		}
		public void Union(int iNumber0 , int iNumber1)
		{
			var rootNumber0 = _GetRoot(iNumber0);
			var rootNumber1 = _GetRoot(iNumber1);
			if(rootNumber0 < rootNumber1)
			{
				Parents[rootNumber1] = rootNumber0;
			}
			else
			{
				Parents[rootNumber0] = rootNumber1;
			}
		}
		public int _GetRoot(int iNumber)
		{
			return (Parents[iNumber] == iNumber) ? iNumber : _GetRoot(Parents[iNumber]);
		}
	}

	public class CumulativeSum
	{
		public static CumulativeSum Create(IEnumerable<long> iNumbers)
		{
			var numbers = iNumbers.ToArray();
			var cumulativeSum = new CumulativeSum
			{
				Numbers = numbers,
				SumNumbers = new long[numbers.Length + 1]
			};
			var sumNumber = 0L;
			for(var iIndex = 0 ; iIndex < numbers.Length ; ++ iIndex)
			{
				sumNumber += numbers[iIndex];
				cumulativeSum.SumNumbers[iIndex + 1] = sumNumber;
			}
			return cumulativeSum;
		}

		public long[] Numbers { get; private set; }
		public long[] SumNumbers { get; private set; }

		public int GetMaxTotalIndex(int iAreaNum)
		{
			var maxIndex = -1;
			var maxNumber = 0L;
			var num = Numbers.Length - iAreaNum + 1;
			for(var iIndex = 0 ; iIndex < num ; ++ iIndex)
			{
				var checkNumber = SumNumbers[iAreaNum + iIndex] - SumNumbers[iIndex];
				if(maxNumber < checkNumber) 
				{
					maxIndex = iIndex;
					maxNumber = checkNumber;
				}
			}
			return maxIndex;
		}
	}
}