use std::io::*;
use std::str::FromStr;
use std::collections::HashMap;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
#[derive(Clone)]
struct FenwickTree {
    seq: Vec<i64>,
}
#[allow(dead_code)]
impl FenwickTree {
    fn new(n: usize) -> FenwickTree {
        FenwickTree {
            seq: vec![0; n + 2],
        }
    }
    fn add(&mut self, index: usize, value: i64) {
        let mut index = (index + 1) as i32;
        while (index as usize) < self.seq.len() {
            self.seq[index as usize] += value;
            index += index & -index;
        }
    }
    // inclusive
    fn sum(&self, index: usize) -> i64 {
        let mut ret = 0;
        let mut index = (index + 1) as i32;
        while index > 0 {
            ret += self.seq[index as usize];
            index -= index & -index;
        }
        ret
    }
}

struct Solver {
    n: usize,
    seq: Vec<(usize, char)>,
    rev_map: HashMap<(usize, char), usize>,
    white_counts: Vec<FenwickTree>,
    black_counts: Vec<FenwickTree>,
    memo: Vec<Vec<i64>>,
}

impl Solver {
    fn new() -> Solver {
        let n = read::<usize>();
        let mut seq = vec![(0, 'W'); 2 * n];
        let mut rev_map = HashMap::<(usize, char), usize>::new();
        let mut white_counts = vec![FenwickTree::new(2 * n + 10); n];
        let mut black_counts = vec![FenwickTree::new(2 * n + 10); n];
        for i in 0..2 * n {
            seq[i].1 = read::<String>().chars().collect::<Vec<char>>()[0];
            seq[i].0 = read::<usize>() - 1;
            rev_map.insert(seq[i], i);
            for j in seq[i].0..n {
                if seq[i].1 == 'W' {
                    white_counts[j].add(i, 1);
                } else {
                    black_counts[j].add(i, 1);
                }
            }
        }
        // println!("{:?}", rev_map);
        let memo = vec![vec![1 << 60; n + 1]; n + 1];
        Solver {
            n: n,
            seq: seq,
            memo: memo,
            rev_map: rev_map,
            white_counts: white_counts,
            black_counts: black_counts,
        }
    }
    fn dist(&self, index: usize, white: usize, black: usize) -> i64 {
        let mut ret = index as i64;
        if white > 0 {
            // println!("{}", self.white_counts[white - 1].sum(index));
            ret -= self.white_counts[white - 1].sum(index);
        }
        if black > 0 {
            // println!("{}", self.black_counts[black - 1].sum(index));
            ret -= self.black_counts[black - 1].sum(index);
        }
        // println!("{} {} {} {}", index, ret, white, black);
        assert!(ret >= 0);
        ret
    }
    fn calc(&mut self, white: usize, black: usize) -> i64 {
        if white == self.n && black == self.n {
            return 0;
        }
        if self.memo[white][black] != (1 << 60) {
            return self.memo[white][black];
        }
        let mut ret = 1 << 60;
        if white != self.n {
            let &index = self.rev_map.get(&(white, 'W')).unwrap();
            let nret = self.dist(index, white, black) + self.calc(white + 1, black);
            ret = std::cmp::min(ret, nret);
        }
        if black != self.n {
            let &index = self.rev_map.get(&(black, 'B')).unwrap();
            let nret = self.dist(index, white, black) + self.calc(white, black + 1);
            ret = std::cmp::min(ret, nret);
        }
        self.memo[white][black] = ret;
        ret
    }
    fn solve(&mut self) {
        let ans = self.calc(0, 0);
        println!("{}", ans);
    }
}

fn main() {
    let mut solver = Solver::new();
    solver.solve();
}


Measured memory_bytes: 193020