Problem:
Score : 600 points

Problem Statement

We have a set S of N points in a two-dimensional plane. The coordinates of the i-th point are (x_i, y_i). The N points have distinct x-coordinates and distinct y-coordinates.

For a non-empty subset T of S, let f(T) be the number of points contained in the smallest rectangle, whose sides are parallel to the coordinate axes, that contains all the points in T. More formally, we define f(T) as follows:

f(T) := (the number of integers i (1 \leq i \leq N) such that a \leq x_i \leq b and c \leq y_i \leq d, where a, b, c, and d are the minimum x-coordinate, the maximum x-coordinate, the minimum y-coordinate, and the maximum y-coordinate of the points in T)

Find the sum of f(T) over all non-empty subset T of S. Since it can be enormous, print the sum modulo 998244353.

Constraints

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

-10^9 \leq x_i, y_i \leq 10^9

x_i \neq x_j (i \neq j)

y_i \neq y_j (i \neq j)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
:
x_N y_N

Output

Print the sum of f(T) over all non-empty subset T of S, modulo 998244353.

Sample Input 1

3
-1 3
2 1
3 -2

Sample Output 1

13

Let the first, second, and third points be P_1, P_2, and P_3, respectively. S = \{P_1, P_2, P_3\} has seven non-empty subsets, and f has the following values for each of them:

f(\{P_1\}) = 1

f(\{P_2\}) = 1

f(\{P_3\}) = 1

f(\{P_1, P_2\}) = 2

f(\{P_2, P_3\}) = 2

f(\{P_3, P_1\}) = 3

f(\{P_1, P_2, P_3\}) = 3

The sum of these is 13.

Sample Input 2

4
1 4
2 1
3 3
4 2

Sample Output 2

34

Sample Input 3

10
19 -11
-3 -12
5 3
3 -15
8 -14
-9 -20
10 -9
0 2
-7 17
6 -6

Sample Output 3

7222

Be sure to print the sum modulo 998244353.

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

pub trait IterScan: Sized {
    type Output;
    fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output>;
}
pub trait MarkedIterScan: Sized {
    type Output;
    fn mscan<'a, I: Iterator<Item = &'a str>>(self, iter: &mut I) -> Option<Self::Output>;
}
#[derive(Debug)]
pub struct Scanner<'a> {
    iter: std::str::SplitAsciiWhitespace<'a>,
}
impl<'a> Scanner<'a> {
    #[inline]
    pub fn new(s: &'a str) -> Self {
        let iter = s.split_ascii_whitespace();
        Self { iter }
    }
    #[inline]
    pub fn scan<T: IterScan>(&mut self) -> <T as IterScan>::Output {
        T::scan(&mut self.iter).unwrap()
    }
    #[inline]
    pub fn mscan<T: MarkedIterScan>(&mut self, marker: T) -> <T as MarkedIterScan>::Output {
        marker.mscan(&mut self.iter).unwrap()
    }
    #[inline]
    pub fn scan_vec<T: IterScan>(&mut self, size: usize) -> Vec<<T as IterScan>::Output> {
        (0..size)
            .map(|_| T::scan(&mut self.iter).unwrap())
            .collect()
    }
    #[inline]
    pub fn scan_chars(&mut self) -> Vec<char> {
        self.iter.next().unwrap().chars().collect::<Vec<char>>()
    }
}
mod scanner_impls {
    use super::*;
    macro_rules !iter_scan_impls {($($t :ty ) *) =>{$(impl IterScan for $t {type Output =Self ;#[inline ] fn scan <'a ,I :Iterator <Item =&'a str >>(iter :&mut I ) ->Option <Self >{iter .next () ?.parse ::<$t >() .ok () } } ) *} ;}
    iter_scan_impls !(char u8 u16 u32 u64 usize i8 i16 i32 i64 isize f32 f64 u128 i128 String ) ;
    macro_rules !iter_scan_tuple_impl {($($T :ident ) *) =>{impl <$($T :IterScan ) ,*>IterScan for ($($T ,) *) {type Output =($(<$T as IterScan >::Output ,) *) ;#[inline ] fn scan <'a ,It :Iterator <Item =&'a str >>(_iter :&mut It ) ->Option <Self ::Output >{Some (($($T ::scan (_iter ) ?,) *) ) } } } ;}
    iter_scan_tuple_impl!();
    iter_scan_tuple_impl!(A);
    iter_scan_tuple_impl !(A B ) ;
    iter_scan_tuple_impl !(A B C ) ;
    iter_scan_tuple_impl !(A B C D ) ;
    iter_scan_tuple_impl !(A B C D E ) ;
    iter_scan_tuple_impl !(A B C D E F ) ;
    iter_scan_tuple_impl !(A B C D E F G ) ;
    iter_scan_tuple_impl !(A B C D E F G H ) ;
    iter_scan_tuple_impl !(A B C D E F G H I ) ;
    iter_scan_tuple_impl !(A B C D E F G H I J ) ;
    iter_scan_tuple_impl !(A B C D E F G H I J K ) ;
    pub struct ScannerIter<'a, 'b, T> {
        inner: &'b mut Scanner<'a>,
        _marker: std::marker::PhantomData<fn() -> T>,
    }
    impl<'a, 'b, T: IterScan> Iterator for ScannerIter<'a, 'b, T> {
        type Item = <T as IterScan>::Output;
        fn next(&mut self) -> Option<Self::Item> {
            T::scan(&mut self.inner.iter)
        }
    }
    impl<'a> Scanner<'a> {
        #[inline]
        pub fn iter<'b, T: IterScan>(&'b mut self) -> ScannerIter<'a, 'b, T> {
            ScannerIter {
                inner: self,
                _marker: std::marker::PhantomData,
            }
        }
    }
}
mod marker {
    use super::*;
    pub struct Usize1;
    impl IterScan for Usize1 {
        type Output = usize;
        #[inline]
        fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output> {
            usize::scan(iter).map(|x| x.wrapping_sub(1))
        }
    }
    pub struct Isize1;
    impl IterScan for Isize1 {
        type Output = isize;
        #[inline]
        fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output> {
            isize::scan(iter).map(|x| x.wrapping_sub(1))
        }
    }
}
#[macro_export]
macro_rules !min {($e :expr ) =>{$e } ;($e :expr ,$($es :expr ) ,+) =>{std ::cmp ::min ($e ,min !($($es ) ,+) ) } ;}
#[macro_export]
macro_rules !chmin {($dst :expr ,$($src :expr ) ,+) =>{{let x =std ::cmp ::min ($dst ,min !($($src ) ,+) ) ;$dst =x ;} } ;}
#[macro_export]
macro_rules !max {($e :expr ) =>{$e } ;($e :expr ,$($es :expr ) ,+) =>{std ::cmp ::max ($e ,max !($($es ) ,+) ) } ;}
#[macro_export]
macro_rules !chmax {($dst :expr ,$($src :expr ) ,+) =>{{let x =std ::cmp ::max ($dst ,max !($($src ) ,+) ) ;$dst =x ;} } ;}
pub trait Modulus {
    fn get_modulus() -> u32;
    #[inline]
    fn modulo(x: u32) -> u32 {
        x % Self::get_modulus()
    }
}
#[allow(unused_macros)]
macro_rules! make_modulus {
    ($t :ident ,$e :expr ) => {
        pub struct $t {}
        impl Modulus for $t {
            #[inline]
            fn get_modulus() -> u32 {
                const MODULUS: u32 = $e;
                MODULUS
            }
        }
    };
}
#[allow(unused_macros)]
macro_rules! make_dynamic_modulus {
    ($t :ident ,$m :ident ,$e :expr ) => {
        pub struct $t {}
        static mut $m: u32 = $e;
        impl Modulus for $t {
            #[inline]
            fn get_modulus() -> u32 {
                unsafe { $m }
            }
        }
    };
}
pub mod modulus {
    use super::*;
    pub struct Modulo1000000007 {}
    impl Modulus for Modulo1000000007 {
        #[inline]
        fn get_modulus() -> u32 {
            const MODULUS: u32 = 1_000_000_007;
            MODULUS
        }
    }
    pub struct Modulo1000000009 {}
    impl Modulus for Modulo1000000009 {
        #[inline]
        fn get_modulus() -> u32 {
            const MODULUS: u32 = 1_000_000_009;
            MODULUS
        }
    }
    pub struct Modulo998244353 {}
    impl Modulus for Modulo998244353 {
        #[inline]
        fn get_modulus() -> u32 {
            const MODULUS: u32 = 998_244_353;
            MODULUS
        }
    }
    pub struct DynModulo {}
    static mut DYN_MODULUS: u32 = 1_000_000_007;
    impl Modulus for DynModulo {
        #[inline]
        fn get_modulus() -> u32 {
            unsafe { DYN_MODULUS }
        }
    }
    pub fn set_dyn_modulus(m: u32) {
        unsafe {
            DYN_MODULUS = m;
        }
    }
}
pub struct MInt<M>
where
    M: Modulus,
{
    x: u32,
    _marker: std::marker::PhantomData<fn() -> M>,
}
impl<M: Modulus> MInt<M> {
    #[inline]
    pub fn new(x: u32) -> Self {
        Self {
            x: M::modulo(x),
            _marker: std::marker::PhantomData,
        }
    }
    #[inline]
    pub fn new_unchecked(x: u32) -> Self {
        Self {
            x,
            _marker: std::marker::PhantomData,
        }
    }
    #[inline]
    pub fn inner(self) -> u32 {
        self.x
    }
    #[inline]
    pub fn one() -> Self {
        Self::new_unchecked(1)
    }
    #[inline]
    pub fn zero() -> Self {
        Self::new_unchecked(0)
    }
    #[inline]
    pub fn get_mod() -> u32 {
        M::get_modulus()
    }
    #[inline]
    pub fn pow(mut self, mut y: usize) -> Self {
        let mut x = Self::one();
        while y > 0 {
            if y & 1 == 1 {
                x *= self;
            }
            self *= self;
            y >>= 1;
        }
        x
    }
    #[inline]
    /// only prime modulus
    pub fn inv(self) -> Self {
        let mut a = self.x;
        let (mut b, mut u, mut s) = (M::get_modulus(), 1, 0);
        let k = a.trailing_zeros();
        a >>= k;
        for _ in 0..k {
            if u & 1 == 1 {
                u += M::get_modulus();
            }
            u /= 2;
        }
        while a != b {
            if b < a {
                std::mem::swap(&mut a, &mut b);
                std::mem::swap(&mut u, &mut s);
            }
            b -= a;
            if s < u {
                s += M::get_modulus();
            }
            s -= u;
            let k = b.trailing_zeros();
            b >>= k;
            for _ in 0..k {
                if s & 1 == 1 {
                    s += M::get_modulus();
                }
                s /= 2;
            }
        }
        Self::new_unchecked(s)
    }
}
mod mint_impls {
    use super::*;
    use std::{
        cmp::Ordering,
        fmt::{self, Debug},
        hash::{Hash, Hasher},
        iter::{Product, Sum},
        marker::PhantomData,
        num::ParseIntError,
        ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
        str::FromStr,
    };
    impl<M: Modulus> Clone for MInt<M> {
        #[inline]
        fn clone(&self) -> Self {
            Self {
                x: Clone::clone(&self.x),
                _marker: PhantomData,
            }
        }
    }
    impl<M: Modulus> Copy for MInt<M> {}
    impl<M: Modulus> Debug for MInt<M> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            Debug::fmt(&self.x, f)
        }
    }
    impl<M: Modulus> Default for MInt<M> {
        #[inline]
        fn default() -> Self {
            Self::zero()
        }
    }
    impl<M: Modulus> PartialEq for MInt<M> {
        #[inline]
        fn eq(&self, other: &Self) -> bool {
            PartialEq::eq(&self.x, &other.x)
        }
    }
    impl<M: Modulus> PartialOrd for MInt<M> {
        #[inline]
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
            PartialOrd::partial_cmp(&self.x, &other.x)
        }
    }
    impl<M: Modulus> Eq for MInt<M> {}
    impl<M: Modulus> Ord for MInt<M> {
        #[inline]
        fn cmp(&self, other: &Self) -> Ordering {
            Ord::cmp(&self.x, &other.x)
        }
    }
    impl<M: Modulus> Hash for MInt<M> {
        #[inline]
        fn hash<H: Hasher>(&self, state: &mut H) {
            Hash::hash(&self.x, state)
        }
    }
    impl<M: Modulus> From<u32> for MInt<M> {
        #[inline]
        fn from(x: u32) -> Self {
            Self::new(x)
        }
    }
    impl<M: Modulus> From<u64> for MInt<M> {
        #[inline]
        fn from(x: u64) -> Self {
            Self::new_unchecked((x % M::get_modulus() as u64) as u32)
        }
    }
    impl<M: Modulus> From<i32> for MInt<M> {
        #[inline]
        fn from(x: i32) -> Self {
            let x = x % M::get_modulus() as i32;
            if x < 0 {
                Self::new_unchecked((x + M::get_modulus() as i32) as u32)
            } else {
                Self::new_unchecked(x as u32)
            }
        }
    }
    impl<M: Modulus> From<i64> for MInt<M> {
        #[inline]
        fn from(x: i64) -> Self {
            let x = x % M::get_modulus() as i64;
            if x < 0 {
                Self::new_unchecked((x + M::get_modulus() as i64) as u32)
            } else {
                Self::new_unchecked(x as u32)
            }
        }
    }
    impl<M: Modulus> Add for MInt<M> {
        type Output = Self;
        #[inline]
        fn add(self, rhs: Self) -> Self::Output {
            let mut x = self.x + rhs.x;
            if x >= M::get_modulus() {
                x -= M::get_modulus();
            }
            Self::new_unchecked(x)
        }
    }
    impl<M: Modulus> Sub for MInt<M> {
        type Output = Self;
        #[inline]
        fn sub(self, rhs: Self) -> Self::Output {
            if self.x < rhs.x {
                Self::new_unchecked(self.x + M::get_modulus() - rhs.x)
            } else {
                Self::new_unchecked(self.x - rhs.x)
            }
        }
    }
    impl<M: Modulus> Mul for MInt<M> {
        type Output = Self;
        #[inline]
        fn mul(self, rhs: Self) -> Self::Output {
            Self::new_unchecked((self.x as u64 * rhs.x as u64 % M::get_modulus() as u64) as u32)
        }
    }
    impl<M: Modulus> Div for MInt<M> {
        type Output = Self;
        #[inline]
        fn div(self, rhs: Self) -> Self::Output {
            self * rhs.inv()
        }
    }
    impl<M: Modulus> Neg for MInt<M> {
        type Output = Self;
        #[inline]
        fn neg(self) -> Self::Output {
            if self.x == 0 {
                Self::zero()
            } else {
                Self::new_unchecked(M::get_modulus() - self.x)
            }
        }
    }
    impl<M: Modulus> Sum for MInt<M> {
        #[inline]
        fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::zero(), Add::add)
        }
    }
    impl<M: Modulus> Product for MInt<M> {
        #[inline]
        fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::one(), Mul::mul)
        }
    }
    impl<'a, M: Modulus + 'a> Sum<&'a MInt<M>> for MInt<M> {
        #[inline]
        fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
            iter.fold(Self::zero(), Add::add)
        }
    }
    impl<'a, M: Modulus + 'a> Product<&'a MInt<M>> for MInt<M> {
        #[inline]
        fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
            iter.fold(Self::one(), Mul::mul)
        }
    }
    impl<M: Modulus> fmt::Display for MInt<M> {
        fn fmt<'a>(&self, f: &mut fmt::Formatter<'a>) -> Result<(), fmt::Error> {
            write!(f, "{}", self.x)
        }
    }
    impl<M: Modulus> FromStr for MInt<M> {
        type Err = ParseIntError;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            s.parse::<u32>().map(Self::new)
        }
    }
    macro_rules! mint_ref_binop {
        ($imp :ident ,$method :ident ,$t :ty ) => {
            impl<M: Modulus> $imp<$t> for &$t {
                type Output = <$t as $imp<$t>>::Output;
                #[inline]
                fn $method(self, other: $t) -> <$t as $imp<$t>>::Output {
                    $imp::$method(*self, other)
                }
            }
            impl<M: Modulus> $imp<&$t> for $t {
                type Output = <$t as $imp<$t>>::Output;
                #[inline]
                fn $method(self, other: &$t) -> <$t as $imp<$t>>::Output {
                    $imp::$method(self, *other)
                }
            }
            impl<M: Modulus> $imp<&$t> for &$t {
                type Output = <$t as $imp<$t>>::Output;
                #[inline]
                fn $method(self, other: &$t) -> <$t as $imp<$t>>::Output {
                    $imp::$method(*self, *other)
                }
            }
        };
    }
    mint_ref_binop!(Add, add, MInt<M>);
    mint_ref_binop!(Sub, sub, MInt<M>);
    mint_ref_binop!(Mul, mul, MInt<M>);
    mint_ref_binop!(Div, div, MInt<M>);
    macro_rules! mint_ref_unop {
        ($imp :ident ,$method :ident ,$t :ty ) => {
            impl<M: Modulus> $imp for &$t {
                type Output = <$t as $imp>::Output;
                #[inline]
                fn $method(self) -> <$t as $imp>::Output {
                    $imp::$method(*self)
                }
            }
        };
    }
    mint_ref_unop!(Neg, neg, MInt<M>);
    macro_rules! mint_ref_op_assign {
        ($imp :ident ,$method :ident ,$t :ty ,$fromimp :ident ,$frommethod :ident ) => {
            impl<M: Modulus> $imp<$t> for $t {
                #[inline]
                fn $method(&mut self, rhs: $t) {
                    *self = $fromimp::$frommethod(*self, rhs);
                }
            }
            impl<M: Modulus> $imp<&$t> for $t {
                #[inline]
                fn $method(&mut self, other: &$t) {
                    $imp::$method(self, *other);
                }
            }
        };
    }
    mint_ref_op_assign!(AddAssign, add_assign, MInt<M>, Add, add);
    mint_ref_op_assign!(SubAssign, sub_assign, MInt<M>, Sub, sub);
    mint_ref_op_assign!(MulAssign, mul_assign, MInt<M>, Mul, mul);
    mint_ref_op_assign!(DivAssign, div_assign, MInt<M>, Div, div);
}
impl<M: Modulus> IterScan for MInt<M> {
    type Output = Self;
    #[inline]
    fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output> {
        iter.next()?.parse::<MInt<M>>().ok()
    }
}
#[derive(Clone, Debug)]
pub struct BinaryIndexedTree<M: Monoid> {
    n: usize,
    bit: Vec<M::T>,
    m: M,
}
impl<M: Monoid> BinaryIndexedTree<M> {
    #[inline]
    pub fn new(n: usize, m: M) -> Self {
        let bit = vec![m.unit(); n + 1];
        Self { n, bit, m }
    }
    #[inline]
    /// fold [0, k)
    pub fn accumulate0(&self, mut k: usize) -> M::T {
        debug_assert!(k <= self.n);
        let mut res = self.m.unit();
        while k > 0 {
            res = self.m.operate(&res, &self.bit[k]);
            k -= k & !k + 1;
        }
        res
    }
    #[inline]
    /// fold [0, k]
    pub fn accumulate(&self, k: usize) -> M::T {
        self.accumulate0(k + 1)
    }
    #[inline]
    pub fn update(&mut self, k: usize, x: M::T) {
        debug_assert!(k < self.n);
        let mut k = k + 1;
        while k <= self.n {
            self.bit[k] = self.m.operate(&self.bit[k], &x);
            k += k & !k + 1;
        }
    }
}
impl<G: Group> BinaryIndexedTree<G> {
    #[inline]
    pub fn fold(&self, l: usize, r: usize) -> G::T {
        debug_assert!(l < self.n && 0 < r && r <= self.n);
        self.m
            .operate(&self.m.inverse(&self.accumulate0(l)), &self.accumulate0(r))
    }
    #[inline]
    pub fn get(&self, k: usize) -> G::T {
        self.fold(k, k + 1)
    }
    #[inline]
    pub fn set(&mut self, k: usize, x: G::T) {
        let y = self.m.inverse(&self.get(k));
        self.update(k, self.m.operate(&y, &x));
    }
}
impl<M: Monoid> BinaryIndexedTree<M>
where
    M::T: Ord,
{
    #[inline]
    pub fn lower_bound(&self, x: M::T) -> usize {
        let n = self.n;
        let mut acc = self.m.unit();
        let mut pos = 0;
        let mut k = 1 << format!("{:b}", n).len();
        while k > 0 {
            if k + pos <= n && self.m.operate(&acc, &self.bit[k + pos]) < x {
                pos += k;
                acc = self.m.operate(&acc, &self.bit[pos]);
            }
            k >>= 1;
        }
        pos
    }
}
/// binary operaion: $T \circ T \to T$
pub trait Magma {
    /// type of operands: $T$
    type T: Clone + PartialEq;
    /// binary operaion: $\circ$
    fn operate(&self, x: &Self::T, y: &Self::T) -> Self::T;
    #[inline]
    fn reverse_operate(&self, x: &Self::T, y: &Self::T) -> Self::T {
        self.operate(x, y)
    }
}
/// $\forall a,\forall b,\forall c \in T, (a \circ b) \circ c = a \circ (b \circ c)$
pub trait Associative {}
/// associative binary operation
pub trait SemiGroup: Magma + Associative {}
impl<S: Magma + Associative> SemiGroup for S {}
/// $\exists e \in T, \forall a \in T, e \circ a = a \circ e = e$
pub trait Unital: Magma {
    /// identity element: $e$
    fn unit(&self) -> Self::T;
}
/// associative binary operation and an identity element
pub trait Monoid: SemiGroup + Unital {
    /// binary exponentiation: $x^n = x\circ\ddots\circ x$
    fn pow(&self, x: Self::T, n: usize) -> Self::T {
        let mut n = n;
        let mut res = self.unit();
        let mut base = x;
        while n > 0 {
            if n & 1 == 1 {
                res = self.operate(&res, &base);
            }
            base = self.operate(&base, &base);
            n = n >> 1;
        }
        res
    }
}
impl<M: SemiGroup + Unital> Monoid for M {}
/// $\exists e \in T, \forall a \in T, \exists b,c \in T, b \circ a = a \circ c = e$
pub trait Invertible: Magma {
    /// $a$ where $a \circ x = e$
    fn inverse(&self, x: &Self::T) -> Self::T;
}
/// short cut of right inverse binary operation
pub trait RightInvertibleMagma: Magma {
    /// right inverse binary operation: $\cdot \circ (\cdot^{-1})$
    fn rinv_operation(&self, x: &Self::T, y: &Self::T) -> Self::T;
}
/// associative binary operation and an identity element and inverse elements
pub trait Group: Monoid + Invertible {}
impl<G: Monoid + Invertible> Group for G {}
/// $\forall a,\forall b \in T, a \circ b = b \circ a$
pub trait Commutative {}
/// commutative monoid
pub trait AbelianMonoid: Monoid + Commutative {}
impl<M: Monoid + Commutative> AbelianMonoid for M {}
/// commutative group
pub trait AbelianGroup: Group + Commutative {}
impl<G: Group + Commutative> AbelianGroup for G {}
/// $\forall a \in T, a \circ a = a$
pub trait Idempotent {}
/// idempotent monoid
pub trait IdempotentMonoid: Monoid + Idempotent {}
impl<M: Monoid + Idempotent> IdempotentMonoid for M {}
/// $+$
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct AdditiveOperation<T: Copy + PartialEq + AdditiveIdentity> {
    _marker: std::marker::PhantomData<fn() -> T>,
}
pub trait AdditiveIdentity: Sized + std::ops::Add<Output = Self> {
    fn zero() -> Self;
}
#[macro_use]
mod additive_operation_impl {
    use super::*;
    #[macro_export(local_inner_macros)]
    macro_rules !impl_additive_identity {([$($wh :tt ) *] ,$t :ty ,$zero :expr ) =>{impl <$($wh ) *>AdditiveIdentity for $t {#[inline ] fn zero () ->Self {$zero } } } ;($t :ty ,$zero :expr ) =>{impl AdditiveIdentity for $t {#[inline ] fn zero () ->Self {$zero } } } ;}
    impl_additive_identity!(usize, 0usize);
    impl_additive_identity!(u8, 0u8);
    impl_additive_identity!(u16, 0u16);
    impl_additive_identity!(u32, 0u32);
    impl_additive_identity!(u64, 0u64);
    impl_additive_identity!(isize, 0isize);
    impl_additive_identity!(i8, 0i8);
    impl_additive_identity!(i16, 0i16);
    impl_additive_identity!(i32, 0i32);
    impl_additive_identity!(i64, 0i64);
    impl_additive_identity!(f32, 0.0f32);
    impl_additive_identity!(f64, 0.0f64);
    impl<T: Copy + PartialEq + AdditiveIdentity> AdditiveOperation<T> {
        pub fn new() -> Self {
            Self {
                _marker: std::marker::PhantomData,
            }
        }
    }
    impl<T: Copy + PartialEq + AdditiveIdentity> Magma for AdditiveOperation<T> {
        type T = T;
        #[inline]
        fn operate(&self, x: &Self::T, y: &Self::T) -> Self::T {
            *x + *y
        }
    }
    impl<T: Copy + PartialEq + AdditiveIdentity> Unital for AdditiveOperation<T> {
        #[inline]
        fn unit(&self) -> Self::T {
            AdditiveIdentity::zero()
        }
    }
    impl<T: Copy + PartialEq + AdditiveIdentity> Associative for AdditiveOperation<T> {}
    impl<T: Copy + PartialEq + AdditiveIdentity> Commutative for AdditiveOperation<T> {}
    impl<T: Copy + PartialEq + AdditiveIdentity + std::ops::Neg<Output = T>> Invertible
        for AdditiveOperation<T>
    {
        #[inline]
        fn inverse(&self, x: &Self::T) -> Self::T {
            -*x
        }
    }
    impl<T: Copy + PartialEq + AdditiveIdentity + std::ops::Sub<Output = T>> RightInvertibleMagma
        for AdditiveOperation<T>
    {
        #[inline]
        fn rinv_operation(&self, x: &Self::T, y: &Self::T) -> Self::T {
            *x - *y
        }
    }
}
/// binary search helper
pub trait Bisect: Copy {
    /// return between two elements
    fn halve(self, other: Self) -> Self;
    /// the end condition of binary search
    fn section_end(self, other: Self) -> bool;
}
mod bisect_impl {
    use super::*;
    macro_rules !impl_bisect_unsigned {($($t :ty ) *) =>{$(impl Bisect for $t {fn halve (self ,other :Self ) ->Self {if self >other {other +(self -other ) /2 } else {self +(other -self ) /2 } } fn section_end (self ,other :Self ) ->bool {(if self >other {self -other } else {other -self } ) <=1 } } ) *} ;}
    macro_rules !impl_bisect_signed {($($t :ty ) *) =>{$(impl Bisect for $t {fn halve (self ,other :Self ) ->Self {(self +other ) /2 } fn section_end (self ,other :Self ) ->bool {(self -other ) .abs () <=1 } } ) *} ;}
    macro_rules !impl_bisect_float {($($t :ty ) *) =>{$(impl Bisect for $t {fn halve (self ,other :Self ) ->Self {(self +other ) /2. } fn section_end (self ,other :Self ) ->bool {(self -other ) .abs () <=1e-8 } } ) *} ;}
    impl_bisect_unsigned !(u8 u16 u32 u64 usize ) ;
    impl_bisect_signed !(i8 i16 i32 i64 isize ) ;
    impl_bisect_float !(f32 f64 ) ;
}
pub fn binary_search<T: Bisect, F: Fn(T) -> bool>(f: F, ok: T, err: T) -> T {
    let mut ok = ok;
    let mut err = err;
    while !ok.section_end(err) {
        let m = ok.halve(err);
        if f(m) {
            ok = m;
        } else {
            err = m;
        }
    }
    ok
}
pub fn lower_bound<T: Bisect + Ord>(v: &[T], x: T) -> usize {
    binary_search(|i| v[i as usize] >= x, v.len() as i64, -1) as usize
}
pub fn upper_bound<T: Bisect + Ord>(v: &[T], x: T) -> usize {
    binary_search(|i| v[i as usize] > x, v.len() as i64, -1) as usize
}
#[derive(Clone, Debug)]
pub struct Compress<T> {
    v: Vec<T>,
}
impl<T: Ord> Compress<T> {
    pub fn get(&self, x: &T) -> usize {
        self.v.binary_search(&x).unwrap()
    }
}
impl<T> Compress<T> {
    pub fn len(&self) -> usize {
        self.v.len()
    }
}
impl<T> std::ops::Index<usize> for Compress<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        &self.v[index]
    }
}
impl<T: Ord> std::iter::FromIterator<T> for Compress<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        use std::collections::BTreeSet;
        let v = iter
            .into_iter()
            .collect::<BTreeSet<T>>()
            .into_iter()
            .collect::<Vec<T>>();
        Self { v }
    }
}
fn main() {
    #[allow(unused_imports)]
    use std::io::{Read as _, Write as _};
    let __out = std::io::stdout();
    let mut __in_buf = String::new();
    std::io::stdin().read_to_string(&mut __in_buf).unwrap();
    let mut __scanner = Scanner::new(&__in_buf);
    #[allow(unused_macros)]
    macro_rules !scan {() =>{scan !(usize ) } ;(($($t :tt ) ,*) ) =>{($(scan !($t ) ) ,*) } ;([$t :tt ;$len :expr ] ) =>{(0 ..$len ) .map (|_ |scan !($t ) ) .collect ::<Vec <_ >>() } ;({$t :tt =>$f :expr } ) =>{$f (scan !($t ) ) } ;(chars ) =>{__scanner .scan_chars () } ;($t :ty ) =>{__scanner .scan ::<$t >() } ;}
    let mut __out = std::io::BufWriter::new(__out.lock());
    #[allow(unused_macros)]
    macro_rules !print {($($arg :tt ) *) =>(::std ::write !(__out ,$($arg ) *) .unwrap () ) }
    #[allow(unused_macros)]
    macro_rules !println {($($arg :tt ) *) =>(::std ::writeln !(__out ,$($arg ) *) .unwrap () ) }
    #[allow(unused_macros)]
    macro_rules! echo {
        ($iter :expr ) => {
            echo!($iter, "\n")
        };
        ($iter :expr ,$sep :expr ) => {
            let mut iter = $iter;
            if let Some(item) = iter.next() {
                print!("{}", item);
            }
            for item in iter {
                print!("{}{}", $sep, item);
            }
            println!();
        };
    }
    let n = scan!();
    let mut xy = scan!([(i64, i64); n]);
    let mut ans = (M::new(2).pow(n) - M::one()) * M::new(n as u32);
    xy.sort();
    let c: Compress<_> = xy.iter().map(|t| t.1).collect();
    let mut l = BinaryIndexedTree::new(n, AdditiveOperation::new());
    let mut r = BinaryIndexedTree::new(n, AdditiveOperation::new());
    for i in 0..n {
        r.update(c.get(&xy[i].1), 1i64);
    }
    for (i, (_x, y)) in xy.iter().cloned().enumerate() {
        r.update(c.get(&y), -1i64);
        let p = l.accumulate(c.get(&y)) as usize;
        let q = r.accumulate(c.get(&y)) as usize;
        let v = vec![p, i - p, n - i - 1 - q, q];
        for i in 0..4 {
            ans += M::new(2).pow(v[i]) - M::one();
            ans -= M::new(2).pow(v[i] + v[(i + 1) % 4]) - M::one();
        }
        l.update(c.get(&y), 1i64);
    }
    println!("{}", ans);
}
type M = MInt<modulus::Modulo998244353>;