Problem:
Score : 600 points

Problem Statement

There is a grid with N rows and N columns of squares. Let (i, j) be the square at the i-th row from the top and the j-th column from the left.

Each of the central (N-2) \times (N-2) squares in the grid has a black stone on it.
Each of the 2N - 1 squares on the bottom side and the right side has a white stone on it.

Q queries are given. We ask you to process them in order.
There are two kinds of queries. Their input format and description are as follows:

1 x: Place a white stone on (1, x). After that, for each black stone between (1, x) and the first white stone you hit if you go down from (1, x), replace it with a white stone.

2 x: Place a white stone on (x, 1). After that, for each black stone between (x, 1) and the first white stone you hit if you go right from (x, 1), replace it with a white stone.

How many black stones are there on the grid after processing all Q queries?

Constraints

3 \leq N \leq 2\times 10^5

0 \leq Q \leq \min(2N-4,2\times 10^5)

2 \leq x \leq N-1

Queries are pairwise distinct.

Input

Input is given from Standard Input in the following format:

N Q
Query_1
\vdots
Query_Q

Output

Print how many black stones there are on the grid after processing all Q queries.

Sample Input 1

5 5
1 3
2 3
1 4
2 2
1 2

Sample Output 1

1

After each query, the grid changes in the following way:

Sample Input 2

200000 0

Sample Output 2

39999200004

Sample Input 3

176527 15
1 81279
2 22308
2 133061
1 80744
2 44603
1 170938
2 139754
2 15220
1 172794
1 159290
2 156968
1 56426
2 77429
1 97459
2 71282

Sample Output 3

31159505795

Solution in Rust (1.42.0) (judge verdict: Accepted)

// SNIPPET read
pub trait Readable {
    type Output;
    const WORD_COUNT: usize;
    fn read_words(words: &[&str]) -> Result<Self::Output, String>;
}
#[macro_export]
macro_rules! readable {
    ( $t:ty, $words_count:expr, |$words:ident| $read_words:expr ) => {
        impl Readable for $t {
            type Output = $t;
            const WORD_COUNT: usize = $words_count;
            fn read_words($words: &[&str]) -> Result<$t, String> {
                Ok($read_words)
            }
        }
    };
}
readable!((), 1, |_ss| ());
readable!(String, 1, |ss| ss[0].to_string());
impl Readable for char {
    type Output = char;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<char, String> {
        let chars: Vec<char> = words[0].chars().collect();
        if chars.len() == 1 {
            Ok(chars[0])
        } else {
            Err(format!("cannot parse `{}` as a char", words[0]))
        }
    }
}
pub struct Chars();
impl Readable for Chars {
    type Output = Vec<char>;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Vec<char>, String> {
        Ok(words[0].chars().collect())
    }
}
pub struct Bytes();
impl Readable for Bytes {
    type Output = Vec<u8>;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Vec<u8>, String> {
        Ok(words[0].bytes().collect())
    }
}
impl Readable for i8 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i8, String> {
        use std::str::FromStr;
        i8::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i8", words[0])
        })
    }
}
impl Readable for u8 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u8, String> {
        use std::str::FromStr;
        u8::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u8", words[0])
        })
    }
}
impl Readable for i16 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i16, String> {
        use std::str::FromStr;
        i16::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i16", words[0])
        })
    }
}
impl Readable for u16 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u16, String> {
        use std::str::FromStr;
        u16::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u16", words[0])
        })
    }
}
impl Readable for i32 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i32, String> {
        use std::str::FromStr;
        i32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i32", words[0])
        })
    }
}
impl Readable for u32 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u32, String> {
        use std::str::FromStr;
        u32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u32", words[0])
        })
    }
}
impl Readable for i64 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i64, String> {
        use std::str::FromStr;
        i64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i64", words[0])
        })
    }
}
impl Readable for u64 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u64, String> {
        use std::str::FromStr;
        u64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u64", words[0])
        })
    }
}
impl Readable for i128 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i128, String> {
        use std::str::FromStr;
        i128::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i64", words[0])
        })
    }
}
impl Readable for u128 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u128, String> {
        use std::str::FromStr;
        u128::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u64", words[0])
        })
    }
}
impl Readable for isize {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<isize, String> {
        use std::str::FromStr;
        <isize>::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as isize", words[0])
        })
    }
}
impl Readable for usize {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<usize, String> {
        use std::str::FromStr;
        <usize>::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as usize", words[0])
        })
    }
}
impl Readable for f32 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<f32, String> {
        use std::str::FromStr;
        f32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as f32", words[0])
        })
    }
}
impl Readable for f64 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<f64, String> {
        use std::str::FromStr;
        f64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as f64", words[0])
        })
    }
}
#[allow(non_camel_case_types)]
pub struct u8_;
impl Readable for u8_ {
    type Output = u8;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u8::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u16_;
impl Readable for u16_ {
    type Output = u16;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u16::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u32_;
impl Readable for u32_ {
    type Output = u32;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u32::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u64_;
impl Readable for u64_ {
    type Output = u64;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u64::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct usize_;
impl Readable for usize_ {
    type Output = usize;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        <usize>::read_words(words).map(|n| n-1)
    }
}
impl<T1: Readable, T2: Readable> Readable for (T1, T2) {
    type Output = (T1::Output, T2::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let val2 = T2::read_words(&words[start..])?;
        Ok((val1, val2))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable> Readable for (T1, T2, T3) {
    type Output = (T1::Output, T2::Output, T3::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let val3 = T3::read_words(&words[start..])?;
        Ok((val1, val2, val3))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable> Readable for (T1, T2, T3, T4) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let val4 = T4::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, T5: Readable> Readable for (T1, T2, T3, T4, T5) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT + T5::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::WORD_COUNT;
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let val5 = T5::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4, val5))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, T5: Readable, T6: Readable> Readable for (T1, T2, T3, T4, T5, T6) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output, T6::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT + T5::WORD_COUNT + T6::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::WORD_COUNT;
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let count5 = T5::WORD_COUNT;
        let val5 = T5::read_words(&words[start .. start+count5])?;
        start += count5;
        let val6 = T6::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4, val5, val6))
    }
}
impl<T: Readable> Readable for [T; 2] {
    type Output = [T::Output; 2];
    const WORD_COUNT: usize = T::WORD_COUNT * 2;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        Ok([val1, val2])
    }
}
impl<T: Readable> Readable for [T; 3] {
    type Output = [T::Output; 3];
    const WORD_COUNT: usize = T::WORD_COUNT * 3;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        Ok([val1, val2, val3])
    }
}
impl<T: Readable> Readable for [T; 4] {
    type Output = [T::Output; 4];
    const WORD_COUNT: usize = T::WORD_COUNT * 4;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        Ok([val1, val2, val3, val4])
    }
}
impl<T: Readable> Readable for [T; 5] {
    type Output = [T::Output; 5];
    const WORD_COUNT: usize = T::WORD_COUNT * 5;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        let val5 = T::read_words(&words[T::WORD_COUNT*4 .. T::WORD_COUNT*5])?;
        Ok([val1, val2, val3, val4, val5])
    }
}
impl<T: Readable> Readable for [T; 6] {
    type Output = [T::Output; 6];
    const WORD_COUNT: usize = T::WORD_COUNT * 6;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        let val5 = T::read_words(&words[T::WORD_COUNT*4 .. T::WORD_COUNT*5])?;
        let val6 = T::read_words(&words[T::WORD_COUNT*5 .. T::WORD_COUNT*6])?;
        Ok([val1, val2, val3, val4, val5, val6])
    }
}
pub trait ReadableFromLine {
    type Output;
    fn read_line(line: &str) -> Result<Self::Output, String>;
}
fn split_into_words(line: &str) -> Vec<&str> {
    line.trim_end_matches('\n').split_whitespace().collect()
}
impl<T: Readable> ReadableFromLine for T {
    type Output = T::Output;
    fn read_line(line: &str) -> Result<T::Output, String> {
        let words = split_into_words(line);
        if words.len() != T::WORD_COUNT {
            return Err(format!("line `{}` has {} words, expected {}",
                               line, words.len(), T::WORD_COUNT));
        }
        T::read_words(&words)
    }
}
pub fn read_words_into_vec<T: Readable>(words: &[&str], line: &str) -> Result<Vec<T::Output>, String> {
    let n = T::WORD_COUNT;
    assert_eq!(words.len() % n, 0);
    let mut result = Vec::new();
    for chunk in words.chunks(n) {
        match T::read_words(chunk) {
            Ok(v) => result.push(v),
            Err(msg) => {
                let fragment_msg = if n == 1 {
                    format!("word {}", result.len())
                } else {
                    let l = result.len();
                    format!("words {}-{}", n*l + 1, (n+1) * l)
                };
                return Err(format!(
                    "{} of line `{}`: {}", fragment_msg, line, msg
                ));
            }
        }
    }
    Ok(result)
}
pub fn split_into_words_for_collection<T: Readable>(
    line: &str, prefix_words_count: usize
) -> Result<Vec<&str>, String> {
    let n = T::WORD_COUNT;
    let words = split_into_words(line);
    if words.len() < prefix_words_count {
        return Err(
            format!("line `{}` has {} words, expected at least {}",
                    line, words.len(), prefix_words_count)
        );
    }
    if (words.len() - prefix_words_count) % T::WORD_COUNT != 0 {
        return Err(
            format!("line `{}` has {} words, expected {} + {}",
                    line, words.len(), prefix_words_count, n)
        );
    }
    Ok(words)
}
#[macro_export]
macro_rules! readable_collection {
    ($u:ident => $collection_in:ty, $collection_out:ty) => {
        readable_collection!($u: => $collection_in, $collection_out);
    };
    ($u:ident : $( $bound:path ),* => $collection_in:ty, $collection_out:ty) => {
        impl<$u: Readable> ReadableFromLine for $collection_in
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = $collection_out;
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let words = split_into_words_for_collection::<$u>(line, 0)?;
                Ok(read_words_into_vec::<$u>(&words, line)?.into_iter().collect())
            }
        }
        impl<T1: Readable, $u: Readable> ReadableFromLine for (T1, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = T1::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let val1 = T1::read_words(&words[..prefix_len])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, $u: Readable> ReadableFromLine for (T1, T2, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, T3: Readable, $u: Readable> ReadableFromLine for (T1, T2, T3, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, T3::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2, T3)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::WORD_COUNT;
                let val3 = T3::read_words(&words[start .. start+count3])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, val3, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, $u: Readable> ReadableFromLine for (T1, T2, T3, T4, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, T3::Output, T4::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2, T3, T4)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::WORD_COUNT;
                let val3 = T3::read_words(&words[start .. start+count3])?;
                start += count3;
                let count4 = T4::WORD_COUNT;
                let val4 = T4::read_words(&words[start .. start+count4])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, val3, val4, rest.into_iter().collect()))
            }
        }
    };
}
readable_collection!(U => Vec<U>, Vec<U::Output>);
pub fn read<T: ReadableFromLine>() -> T::Output {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).unwrap();
    T::read_line(&line).unwrap()
}
#[macro_export]
macro_rules! read {
    () => {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).unwrap();
    };
    ( $pat:pat = $t:ty $(,)* ) => {
        let $pat = read::<$t>();
    };
    ( ! $(,)* ) => {
        let _ = read::<()>();
    };
    ( $pat:pat = $t:ty, $( $rest:tt )+ ) => {
        read_inner!($pat = $t; $($rest)+);
    };
    ( !, $( $rest:tt )+ ) => {
        read_inner!(_ = (); $($rest)+);
    };
}
#[macro_export]
#[doc(hidden)]
macro_rules! read_inner {
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; $pat:pat = $t:ty, $( $rest:tt )* ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , $pat = $t ; $($rest)*);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; !, $( $rest:tt )* ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , _ = () ; $($rest)*);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; $pat:pat = $t:ty ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , $pat = $t ;);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; ! ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , _ = () ;);
    };
    ( $( $pat:pat = $t:ty ),+ ; ) => {
        let ($($pat),+) = read::<($($t),+)>();
    };
}
pub trait ReadableFromChunk {
    type Output;
    fn lines_count() -> usize;
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String>;
}
impl<T1: ReadableFromLine, T2: ReadableFromLine> ReadableFromChunk for (T1, T2) {
    type Output = (T1::Output, T2::Output);
    fn lines_count() -> usize { 2 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        Ok((out1, out2))
    }
}
impl<T1: ReadableFromLine, T2: ReadableFromLine, T3: ReadableFromLine> ReadableFromChunk for (T1, T2, T3) {
    type Output = (T1::Output, T2::Output, T3::Output);
    fn lines_count() -> usize { 3 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        let out3 = T3::read_line(&lines[2])?;
        Ok((out1, out2, out3))
    }
}
impl<T1: ReadableFromLine, T2: ReadableFromLine, T3: ReadableFromLine, T4: ReadableFromLine> ReadableFromChunk for (T1, T2, T3, T4) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
    fn lines_count() -> usize { 4 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        let out3 = T3::read_line(&lines[2])?;
        let out4 = T4::read_line(&lines[3])?;
        Ok((out1, out2, out3, out4))
    }
}
pub fn read_chunk<T: ReadableFromChunk>() -> T::Output {
    let stdin = std::io::stdin();
    let mut handle = stdin.lock();
    read_chunk_from_handle::<T>(&mut handle).unwrap()
}
fn read_chunk_from_handle<T: ReadableFromChunk>(handle: &mut std::io::StdinLock) -> Option<T::Output> {
    use std::io::BufRead;
    let mut lines = vec![String::new(); T::lines_count()];
    let mut first = true;
    for line in &mut lines {
        if handle.read_line(line).unwrap() == 0 && first {
            return None;
        }
        first = false;
    }
    Some(T::read_chunk(&lines).unwrap())
}
#[macro_export]
macro_rules! read_chunk {
    ( $( $pat:pat = $t:ty ),+ ) => {
        let ($($pat),+) = read_chunk::<($($t),+)>();
    };
}
static mut STDIN: Option<std::io::Stdin> = None;
pub struct ReadLines<T: ReadableFromLine> {
    lock: std::io::StdinLock<'static>,
    phantom: std::marker::PhantomData<T>
}
impl<T: ReadableFromLine> Iterator for ReadLines<T> {
    type Item = T::Output;
    fn next(&mut self) -> Option<T::Output> {
        use std::io::BufRead;
        let mut line = String::new();
        if self.lock.read_line(&mut line).unwrap() > 0 {
            Some(T::read_line(&line).unwrap())
        } else {
            None
        }
    }
}
pub fn read_lines<T: ReadableFromLine>() -> ReadLines<T> {
    unsafe {
        if STDIN.is_none() {
            STDIN = Some(std::io::stdin());
        }
    }
    ReadLines {
        lock: unsafe { STDIN.as_ref().unwrap().lock() },
        phantom: std::marker::PhantomData::<T>
    }
}
pub struct ReadChunks<T: ReadableFromChunk> {
    lock: std::io::StdinLock<'static>,
    phantom: std::marker::PhantomData<T>
}
impl<T: ReadableFromChunk> Iterator for ReadChunks<T> {
    type Item = T::Output;
    fn next(&mut self) -> Option<T::Output> {
        read_chunk_from_handle::<T>(&mut self.lock)
    }
}
pub fn read_chunks<T: ReadableFromChunk>() -> ReadChunks<T> {
    unsafe {
        if STDIN.is_none() {
            STDIN = Some(std::io::stdin());
        }
    }
    ReadChunks {
        lock: unsafe { STDIN.as_ref().unwrap().lock() },
        phantom: std::marker::PhantomData::<T>
    }
}
pub trait Words {
    fn read<T: Readable>(&self) -> T::Output;
}
impl<'a> Words for [&'a str] {
    fn read<T: Readable>(&self) -> T::Output {
        T::read_words(self).unwrap()
    }
}
impl<'a> Words for &'a str {
    fn read<T: Readable>(&self) -> T::Output {
        T::read_words(&[self]).unwrap()
    }
}

// SNIPPET utils
#[macro_export]
macro_rules! echo {
    () => {
        println!()
    };
    ($e: expr $(,)?) => {
        println!("{}", $e)
    };
    ($e: expr, $($es: expr),+ $(,)?) => {
        {
            use std::io::Write;
            let stdout = std::io::stdout();
            let mut handle = stdout.lock();
            write!(handle, "{}", $e).unwrap();
            $(
                write!(handle, " {}", $es).unwrap();
            )+
            writeln!(handle).unwrap();
        }
    };
}
pub fn yn(result: bool) {
    if result {
        println!("Yes");
    } else {
        println!("No");
    }
}
#[allow(non_snake_case)]
pub fn YN(result: bool) {
    if result {
        println!("YES");
    } else {
        println!("NO");
    }
}
pub fn exit(msg: impl std::fmt::Display) -> ! {
    println!("{}", msg);
    std::process::exit(0)
}
#[macro_export]
#[cfg(local)]
macro_rules! dbg {
    () => {
        {
            use std::io::{self, Write};
            writeln!(io::stderr(), "{}: dbg", line!()).unwrap();
        }
    };
    ($e: expr) => {
        {
            use std::io::{self, Write};
            let result = $e;
            writeln!(io::stderr(), "{}: {} = {:?}",
                     line!(), stringify!($e), result)
                .unwrap();
            result
        }
    }
}
#[macro_export]
#[cfg(not(local))]
macro_rules! dbg {
    () => {};
    ($e: expr) => {
        { $e }
    }
}

// SNIPPET cmp
use std::cmp::{Ord, Ordering};
pub fn minmax<T: Ord>(a: T, b: T) -> (T, T) {
    if a <= b { (a, b) } else { (b, a) }
}
#[macro_export]
macro_rules! chmin {
    ($place: expr, $expr: expr) => {
        let value = $expr;
        if value < $place {
            $place = value;
        }
    }
}
#[macro_export]
macro_rules! chmax {
    ($place: expr, $expr: expr) => {
        let value = $expr;
        if value > $place {
            $place = value;
        }
    }
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Hash)]
pub struct Reverse<T: Ord>(pub T);
impl<T: Ord> PartialOrd for Reverse<T> {
    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}
impl<T: Ord> Ord for Reverse<T> {
    fn cmp(&self, other: &Reverse<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}
pub trait SortDesc<T> {
    fn sort_desc(&mut self) where T: Ord;
    fn sort_desc_by<F>(&mut self, cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering;
    fn sort_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, key: F);
    fn sort_unstable_desc(&mut self) where T: Ord;
    fn sort_unstable_desc_by<F>(&mut self, cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering;
    fn sort_unstable_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, key: F);
}
impl<T> SortDesc<T> for [T] {
    fn sort_desc(&mut self) where T: Ord {
        self.sort_by(|x, y| y.cmp(x));
    }
    fn sort_desc_by<F>(&mut self, mut cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering
    {
        self.sort_by(|x, y| cmp(y, x));
    }
    fn sort_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, mut key: F) {
        self.sort_by_key(|x| Reverse(key(x)));
    }
    fn sort_unstable_desc(&mut self) where T: Ord {
        self.sort_unstable_by(|x, y| y.cmp(x));
    }
    fn sort_unstable_desc_by<F>(&mut self, mut cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering
    {
        self.sort_unstable_by(|x, y| cmp(y, x));
    }
    fn sort_unstable_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, mut key: F) {
        self.sort_unstable_by_key(|x| Reverse(key(x)));
    }
}
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default, Hash)]
pub struct Total<T: PartialOrd + PartialEq>(pub T);
impl<T: PartialOrd + PartialEq> Eq for Total<T> {}
impl<T: PartialOrd + PartialEq> Ord for Total<T> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}
pub trait IteratorMinmax: Iterator {
    fn minmax(self) -> Option<(Self::Item, Self::Item)>;
    fn minmax_by_key<K, F>(self, key_fn: F) -> Option<(Self::Item, Self::Item)>
    where
        K: Ord,
        F: FnMut(&Self::Item) -> K;
    fn minmax_by<F>(self, compare: F) -> Option<(Self::Item, Self::Item)>
    where
        F: FnMut(&Self::Item, &Self::Item) -> Ordering;
}
impl<T: Ord + Clone, I: Iterator<Item=T>> IteratorMinmax for I {
    fn minmax(self) -> Option<(Self::Item, Self::Item)> {
        self.minmax_by(|a, b| a.cmp(b))
    }
    fn minmax_by_key<K, F>(self, mut key_fn: F) -> Option<(Self::Item, Self::Item)>
    where
        K: Ord,
        F: FnMut(&Self::Item) -> K
    {
        self.minmax_by(|a, b| key_fn(a).cmp(&key_fn(b)))
    }
    fn minmax_by<F>(mut self, mut compare: F) -> Option<(Self::Item, Self::Item)>
    where
        F: FnMut(&Self::Item, &Self::Item) -> Ordering
    {
        let first = self.next()?;
        let second = match self.next() {
            Some(x) => x,
            None => return Some((first.clone(), first))
        };
        let mut result = minmax(first, second);
        while let Some(x) = self.next() {
            let (min, max) = result;
            result = if compare(&x, &min) == Ordering::Less {
                (x, max)
            } else if compare(&max, &x) == Ordering::Less {
                (min, x)
            } else {
                (min, max)
            };
        }
        Some(result)
    }
}
pub trait WithCmpIdentity<T>: Sized {
    fn new(x: T) -> Self;
    fn inf() -> Self;
    fn as_option(&self) -> Option<&T>;
    fn as_option_mut(&mut self) -> Option<&mut T>;
    fn into_option(self) -> Option<T>;
    fn is_fin(&self) -> bool {
        self.as_option().is_some()
    }
    fn is_inf(&self) -> bool {
        self.as_option().is_none()
    }
    fn expect_fin(self, msg: &str) -> T {
        self.into_option().expect(msg)
    }
    fn fin(self) -> T {
        self.into_option().unwrap()
    }
    fn fin_or(self, default: T) -> T {
        self.into_option().unwrap_or(default)
    }
    fn fin_or_else<F: FnOnce() -> T>(self, f: F) -> T {
        self.into_option().unwrap_or_else(f)
    }
    fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
        self.into_option().map_or(default, f)
    }
    fn map_or_else<U, D, F>(self, default: D, f: F) -> U
    where
        D: FnOnce() -> U,
        F: FnOnce(T) -> U
    {
        self.into_option().map_or_else(default, f).into()
    }
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum MaybeNegInf<T> {
    Inf,
    Fin(T)
}
pub type Max<T> = MaybeNegInf<T>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum MaybeInf<T> {
    Fin(T),
    Inf
}
pub type Min<T> = MaybeInf<T>;
macro_rules! impl_with_cmp_identity {
    ($t:ident) => {
        impl<T> $t<T> {
            pub fn map<U: Ord, F: FnOnce(T) -> U>(self, f: F) -> $t<U> {
                match self {
                    $t::Fin(x) => $t::Fin(f(x)),
                    $t::Inf => $t::Inf
                }
            }
        }
        impl<T> WithCmpIdentity<T> for $t<T> {
            fn new(x: T) -> $t<T> { $t::Fin(x) }
            fn inf() -> $t<T> { $t::Inf }
            fn as_option(&self) -> Option<&T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
            fn as_option_mut(&mut self) -> Option<&mut T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
            fn into_option(self) -> Option<T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
        }
    }
}
impl_with_cmp_identity!(MaybeNegInf);
impl_with_cmp_identity!(MaybeInf);

// END SNIPPETS
// Here is the documentation: https://yoshrc.github.io/rust-atcoder-snippets/atcoder_snippets/index.html

use std::collections::BTreeMap;

fn main() {
    read!(n = usize, !);
    let mut ver = BTreeMap::new();
    ver.insert(n, n-2);
    let mut hor = BTreeMap::new();
    hor.insert(n, n-2);
    let mut ans = (n-2) * (n-2);

    for (query_type, x) in read_lines::<(usize, usize)>() {
        let (take, opp) = if query_type == 1 {
            (&mut ver, &mut hor)
        } else {
            (&mut hor, &mut ver)
        };

        let count = *take.range(x..).next().unwrap().1;
        dbg!(count);
        ans -= count;
        take.insert(x, count);
        chmin!(*opp.values_mut().next().unwrap(), x - 2);

        dbg!((&ver, &hor));
    }

    echo!(ans);
}