fn read_stdin() -> String {
    use std::io::Read;
    let mut input = String::new();
    std::io::stdin().read_to_string(&mut input).unwrap();
    input
}

fn scan<'a, I: Iterator<Item = &'a str>, T: std::str::FromStr>(tokens: &mut I) -> T {
    tokens.next().unwrap().parse().ok().unwrap()
}

fn vec<T, F: FnMut(usize) -> T>(n: usize, mut f: F) -> Vec<T> {
    (0..n).map(|i| f(i)).collect()
}

fn main() {
    let input = read_stdin();
    let tokens = &mut input.split_whitespace();
    let n: usize = scan(tokens);
    // [y0, y1, ..] where x0 < x1 < ...
    let y: Vec<i64> = {
        let mut xy: Vec<(i64, i64)> = vec(n, |_| (scan(tokens), scan(tokens)));
        xy.sort();
        xy.iter().map(|&(_, yi)| yi).collect()
    };
    // p[i] = #{ j | y[j] < y[i] }
    let p: Vec<usize> = {
        let mut y_sorted = y.clone();
        y_sorted.sort();
        y.iter().map(|&yi| binsearch(&y_sorted, yi)).collect()
    };
    // q[i] = # { j < i | y[j] < y[i] }
    let q: Vec<usize> = {
        let mut ct = CountTree::new();
        y.iter().map(|&yi| ct.insert(yi)).collect()
    };
    let mut ans = 0;
    for i in 0..n {
        ans += power(2, n);
        ans += MODULO - power(2, i);
        ans += MODULO - power(2, n - 1 - i);
        ans += MODULO - power(2, p[i]);
        ans += MODULO - power(2, n - 1 - p[i]);
        ans += power(2, q[i]);
        ans += power(2, i - q[i]);
        ans += power(2, p[i] - q[i]);
        ans += power(2, (n - 1 - i) - (p[i] - q[i]));
        ans += MODULO - 1;
        ans %= MODULO;
    }
    println!("{}", ans);
}

const MODULO: usize = 998244353;

fn binsearch(xs: &[i64], x: i64) -> usize {
    let mut a = 0;
    let mut b = xs.len();
    loop {
        let c = (a + b) / 2;
        if xs[c] == x {
            return c;
        }
        if xs[c] < x {
            a = c;
        } else {
            b = c;
        }
    }
}

fn power(mut b: usize, mut e: usize) -> usize {
    let mut a = 1;
    while e != 0 {
        if e & 1 != 0 {
            a = a * b % MODULO;
        }
        b = b * b % MODULO;
        e >>= 1;
    }
    a
}

struct CountTree(Option<Box<Node>>);

impl CountTree {
    fn new() -> Self {
        CountTree(None)
    }
    fn insert(&mut self, x: i64) -> usize {
        if let Some(node) = self.0.take() {
            match Node::insert(node, x) {
                (count, node, None) => {
                    self.0 = Some(node);
                    count
                }
                (count, n1, Some(n2)) => {
                    self.0 = Some(Node::node2(n1, n2));
                    count
                }
            }
        } else {
            self.0 = Some(Node::leaf(x));
            0
        }
    }
}

enum Node {
    Leaf(i64),
    Node2(usize, i64, Box<Node>, Box<Node>),
    Node3(usize, i64, Box<Node>, Box<Node>, Box<Node>),
}

impl Node {
    fn leaf(x: i64) -> Box<Node> {
        Box::new(Node::Leaf(x))
    }
    fn node2(n1: Box<Node>, n2: Box<Node>) -> Box<Node> {
        let len = n1.len() + n2.len();
        Box::new(Node::Node2(len, n1.min(), n1, n2))
    }
    fn node3(n1: Box<Node>, n2: Box<Node>, n3: Box<Node>) -> Box<Node> {
        let len = n1.len() + n2.len() + n3.len();
        Box::new(Node::Node3(len, n1.min(), n1, n2, n3))
    }
    fn len(&self) -> usize {
        match *self {
            Node::Leaf(_) => 1,
            Node::Node2(l, _, _, _) => l,
            Node::Node3(l, _, _, _, _) => l,
        }
    }
    fn min(&self) -> i64 {
        match *self {
            Node::Leaf(x) => x,
            Node::Node2(_, m, _, _) => m,
            Node::Node3(_, m, _, _, _) => m,
        }
    }
    fn insert(node: Box<Node>, x: i64) -> (usize, Box<Node>, Option<Box<Node>>) {
        let node: Node = *node;
        match node {
            Node::Leaf(y) => {
                if x < y {
                    (0, Node::leaf(x), Some(Node::leaf(y)))
                } else {
                    (1, Node::leaf(y), Some(Node::leaf(x)))
                }
            }
            Node::Node2(_, _, n1, n2) => {
                if x < n2.min() {
                    match Node::insert(n1, x) {
                        (c, n1, None) => (c, Node::node2(n1, n2), None),
                        (c, n11, Some(n12)) => (c, Node::node3(n11, n12, n2), None),
                    }
                } else {
                    match Node::insert(n2, x) {
                        (c, n2, None) => (n1.len() + c, Node::node2(n1, n2), None),
                        (c, n21, Some(n22)) => (n1.len() + c, Node::node3(n1, n21, n22), None),
                    }
                }
            }
            Node::Node3(_, _, n1, n2, n3) => {
                if x < n2.min() {
                    match Node::insert(n1, x) {
                        (c, n1, None) => (c, Node::node3(n1, n2, n3), None),
                        (c, n11, Some(n12)) => {
                            (c, Node::node2(n11, n12), Some(Node::node2(n2, n3)))
                        }
                    }
                } else if x < n3.min() {
                    match Node::insert(n2, x) {
                        (c, n2, None) => (n1.len() + c, Node::node3(n1, n2, n3), None),
                        (c, n21, Some(n22)) => (
                            n1.len() + c,
                            Node::node2(n1, n21),
                            Some(Node::node2(n22, n3)),
                        ),
                    }
                } else {
                    match Node::insert(n3, x) {
                        (c, n3, None) => (n1.len() + n2.len() + c, Node::node3(n1, n2, n3), None),
                        (c, n31, Some(n32)) => (
                            n1.len() + n2.len() + c,
                            Node::node2(n1, n2),
                            Some(Node::node2(n31, n32)),
                        ),
                    }
                }
            }
        }
    }
}


Measured memory_bytes: 33012