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 Kotlin (1.0.0) (judge verdict: Time Limit Exceeded)

import java.lang.Math.min
class SumBinaryIndexedTree(implement: BinaryIndexedTree<Int>):BinaryIndexedTree<Int> by implement{
    companion object {
        inline operator fun invoke(size:Int):SumBinaryIndexedTree{
            return SumBinaryIndexedTree(BinaryIndexedTreeTemplate<Int>(size, 0, Int::plus))
        }
    }
}

interface BinaryIndexedTree<T> {
    operator fun get(index:Int):T
    fun plusAt(index:Int, diff:T):Unit
}
class BinaryIndexedTreeTemplate<T> (val size:Int, private val monoidPlus:(T, T) -> T, private val mArray:Array<T>): BinaryIndexedTree<T>{
    companion object {
        inline operator fun <reified T> invoke(size:Int, zero:T, noinline monoidPlus:(T, T) -> T):BinaryIndexedTreeTemplate<T>{
            return BinaryIndexedTreeTemplate(size, monoidPlus, Array(size){zero})
        }
    }
    private inline fun up(index:Int):Int{
        return index + ((index + 1) and (index.inv()))
    }
    private inline fun left(index:Int):Int{
        return index - ((index + 1) and (index.inv()))
    }
    private fun accumulate(a:T, b:T):T = monoidPlus(a, b)
    override operator fun get(index:Int):T{
        var idx = left(index)
        var res = mArray[index]
        while (idx >= 0){
            res = accumulate(res, mArray[idx])
            idx = left(idx)
        }
        return res
    }
    override fun plusAt(index:Int, diff:T):Unit{
        var idx = index
        while (idx < mArray.size){
            mArray[idx] = accumulate(diff, mArray[idx])
            idx = up(idx)
        }
    }
}
fun main(args:Array<String>):Unit {
    val n = readLine()!!.toInt()
    val balls = Array(2 * n) {
        val (c, i) = readLine()!!.split(' ')
        when (c) {
            "B" -> Ball(Color.Black, i.toInt())
            else -> Ball(Color.White, i.toInt())
        }
    }
    val blackCost = Array(n + 1){Array(n + 1){0}} 
    val whiteCost = Array(n + 1){Array(n + 1){0}}
    val blackBit = SumBinaryIndexedTree(n + 1)
    val whiteBit = SumBinaryIndexedTree(n + 1)
    for (i in 0 until 2 * n){
        val ball = balls[i]
        when(ball.color){
            Color.White -> {
                whiteBit.plusAt(ball.number, 1)
                for (j in 0 .. n){
                    whiteCost[ball.number][j] = ball.number - whiteBit[ball.number] + blackBit[n] - blackBit[j]
                }
            }
            Color.Black -> {
                blackBit.plusAt(ball.number, 1)
                for (j in 0..n) {
                    blackCost[ball.number][j] = ball.number - blackBit[ball.number] + whiteBit[n] - whiteBit[j]
                }
            }
        }
    }
    println(f(n, n, blackCost, whiteCost, Array(n + 1){Array(n + 1){-1}}))
}
fun f(b:Int, w:Int, blackCost:Array<Array<Int>>, whiteCost:Array<Array<Int>>, memo:Array<Array<Int>>):Int{
    if (b == 0 && w == 0) return 0
    if (b < 0 || w < 0) return Int.MAX_VALUE shr 2
    if (memo[b][w] < 0){
        memo[b][w] = min(f(b - 1, w, blackCost, whiteCost, memo) + blackCost[b][w], f(b, w - 1, blackCost, whiteCost, memo) + whiteCost[w][b])
    }
    return memo[b][w]
}

enum class Color{
    Black,White
}
data class Ball(val color:Color, val number:Int)