Problem:
Score : 600 points

Problem Statement

There are 2N balls, N white and N black, arranged in a row. The integers from 1 through N are written on the white balls, one on each ball, and they are also written on the black balls, one on each ball.
The integer written on the i-th ball from the left (1 ≤ i ≤ 2N) is a_i, and the color of this ball is represented by a letter c_i.
c_i = W represents the ball is white; c_i = B represents the ball is black.

Takahashi the human wants to achieve the following objective:

For every pair of integers (i,j) such that 1 ≤ i < j ≤ N, the white ball with i written on it is to the left of the white ball with j written on it.

For every pair of integers (i,j) such that 1 ≤ i < j ≤ N, the black ball with i written on it is to the left of the black ball with j written on it.

In order to achieve this, he can perform the following operation:

Swap two adjacent balls.

Find the minimum number of operations required to achieve the objective.

Constraints

1 ≤ N ≤ 2000

1 ≤ a_i ≤ N

c_i = W or c_i = B.

If i ≠ j, (a_i,c_i) ≠ (a_j,c_j).

Input

Input is given from Standard Input in the following format:

N
c_1 a_1
c_2 a_2
:
c_{2N} a_{2N}

Output

Print the minimum number of operations required to achieve the objective.

Sample Input 1

3
B 1
W 2
B 3
W 1
W 3
B 2

Sample Output 1

4

The objective can be achieved in four operations, for example, as follows:

Swap the black 3 and white 1.

Swap the white 1 and white 2.

Swap the black 3 and white 3.

Swap the black 3 and black 2.

Sample Input 2

4
B 4
W 4
B 3
W 3
B 2
W 2
B 1
W 1

Sample Output 2

18

Sample Input 3

9
W 3
B 1
B 4
W 1
B 5
W 9
W 2
B 6
W 5
B 3
W 8
B 9
W 7
B 2
B 8
W 4
W 6
B 7

Sample Output 3

41

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using static System.Math;

class P
{
    static void Main()
    {
        int n = int.Parse(Console.ReadLine());
        List<Ball> balls = Enumerable.Repeat(0, n + n).Select(_ => Console.ReadLine().Split()).Select(x => new Ball(int.Parse(x[1]), x[0][0])).ToList();
        //早めに後ろを持ってくると嬉しいことってある?→ない(逆にじゃまになるので、前からどけたほうがいい)
        //嘘、黒を前に、白を後ろに集めるとかすると嬉しいかもしれない
        int count = 0;
        #region v1
        /*for (int i = 0; i < balls.Count; i++)
        {
            Ball ball = balls[i];
            int ind = i;
            //前を見てソートされてるか確認
            for (int j = i - 1; j >= 0; j--)
            {
                if (balls[j].color != ball.color) continue;
                if (balls[j].num > ball.num) ind = j;
            }
            balls.RemoveAt(i);
            balls.Insert(ind, ball);
            count += (i - ind);
        }*/
        #endregion
        int bw = solve(balls.ToList());
        int wb = solve(balls.Select(x => new Ball(x.num, x.color == 'B' ? 'W' : 'B')).ToList());
        Console.WriteLine(Min(bw, wb));
    }
    static int solve(List<Ball> balls)
    {
        int count = 0;
        int i = 0;

        #region v2
        /*while (i < balls.Count)
        {
            Ball ball = balls[i];
            int ind = i;
            if (ball.color == 'B')
            {
                //前を見てソートされてるか確認
                for (int j = i - 1; j >= 0; j--)
                {
                    if (balls[j].color != ball.color) continue;
                    if (balls[j].num > ball.num) ind = j;
                }
            }
            else
            {
                //白なら後ろに小さいのがあればその後ろにつける
                for (int j = i + 1; j < balls.Count; j++)
                {
                    if (balls[j].color != ball.color) continue;
                    if (balls[j].num < ball.num) ind = j;
                }
            }
            balls.RemoveAt(i);
            balls.Insert(ind, ball);
            count += Abs(i - ind);
            if (Abs(i - ind) == 0) i++;
        }*/
        #endregion
        while (i < balls.Count / 2)
        {
            //前からi番目のWをsort
            int co = 0;
            int ind = 0;
            for (int j = 0; j < balls.Count; j++)
            {
                if (balls[j].color == 'W')
                {
                    co++;
                }
                if(i + 1 == co)
                {
                    ind = j;
                    break;
                }
            }
            Ball ball = balls[ind];
            for (int j = ind - 1; j >= 0; j--)
            {
                if (balls[j].color != ball.color) continue;
                if (balls[j].num > ball.num) ind = j;
            }
            balls.RemoveAt(i);
            balls.Insert(ind, ball);
            count += Abs(i - ind);
            //後ろからj番目のBをsort
            co = 0;
            ind = 0;
            for (int j = balls.Count - 1; j >= 0; j--)
            {
                if (balls[j].color == 'B')
                {
                    co--;
                }
                if (i + 1 == co)
                {
                    ind = j;
                    break;
                }
            }
            ball = balls[ind];
            //白なら後ろに小さいのがあればその後ろにつける
            for (int j = i + 1; j < balls.Count; j++)
            {
                if (balls[j].color != ball.color) continue;
                if (balls[j].num < ball.num) ind = j;
            }
            balls.RemoveAt(i);
            balls.Insert(ind, ball);
            count += Abs(i - ind);
            i++;
        }
        return count;
    }
}

struct Ball
{
    public int num;
    public char color;
    public Ball(int num,char color)
    {
        this.num = num;
        this.color = color;
    }
    public override string ToString() => $"{color} {num}";
}