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

#[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)]
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
    }
}

const MOD: usize = 998244353;
fn main() {
    let n = read::<usize>();
    let mut pow2 = vec![1; n + 10];
    for i in 0..n {
        pow2[i + 1] = pow2[i] * 2 % MOD;
    }
    let mut ps = vec![(0, 0); n];
    {
        let mut ys = BTreeMap::<i64, i64>::new();
        for i in 0..n {
            ps[i].0 = read::<i64>();
            ps[i].1 = read::<i64>();
            ys.insert(ps[i].1, 0);
        }
        let mut cnt = 0;
        let mut yto = BTreeMap::<i64, i64>::new();
        for e in ys.iter() {
            yto.insert(*e.0, cnt);
            cnt += 1;
        }
        for i in 0..n {
            ps[i].1 = yto[&ps[i].1];
        }
    }
    ps.sort();
    let mut ltree = FenwickTree::new(n + 10);
    let mut rtree = FenwickTree::new(n + 10);
    for i in 0..n {
        rtree.add(ps[i].1 as usize, 1);
    }
    let mut ans = 0;
    for &(_x, y) in ps.iter() {
        let y = y as usize;
        rtree.add(y, -1);
        // 0 2
        // 1 3
        let mut cnts = vec![0, 0, 0, 0];
        cnts[0] = ltree.sum(y) as usize;
        cnts[1] = (ltree.sum(n) - ltree.sum(y)) as usize;
        cnts[2] = rtree.sum(y) as usize;
        cnts[3] = (rtree.sum(n) - rtree.sum(y)) as usize;
        // use self
        ans = (ans + pow2[n - 1]) % MOD;
        // use 0 & 3
        let cnt = (pow2[cnts[0]] + MOD - 1) * (pow2[cnts[3]] + MOD - 1) % MOD;
        ans = (ans + cnt) % MOD;
        ans = (ans + cnt * (pow2[cnts[1]] + MOD - 1)) % MOD;
        ans = (ans + cnt * (pow2[cnts[2]] + MOD - 1)) % MOD;
        // use 1 & 2
        let cnt = (pow2[cnts[1]] + MOD - 1) * (pow2[cnts[2]] + MOD - 1) % MOD;
        ans = (ans + cnt) % MOD;
        ans = (ans + cnt * (pow2[cnts[0]] + MOD - 1)) % MOD;
        ans = (ans + cnt * (pow2[cnts[3]] + MOD - 1)) % MOD;
        // use all
        let cnt = (pow2[cnts[0]] + MOD - 1) * (pow2[cnts[1]] + MOD - 1) % MOD
            * (pow2[cnts[2]] + MOD - 1)
            % MOD
            * (pow2[cnts[3]] + MOD - 1)
            % MOD;
        ans = (ans + cnt) % MOD;

        ltree.add(y, 1);
    }
    println!("{}", ans);
}


Measured memory_bytes: 22780