#include <algorithm>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

#define rep(i, n) for (int64_t i = 0; i < (n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)

template <int64_t MOD>
class Modint {
  using Self = Modint<MOD>;

  int64_t m_value;

 public:
  Modint(int64_t value) : m_value((value % MOD + MOD) % MOD) {}
  Self pow(int64_t e) const {
    if (e == 0) {
      return (Self)1;
    } else if (e % 2 == 0) {
      return ((*this) * (*this)).pow(e / 2);
    } else {
      return (*this).pow(e - 1) * (*this);
    }
  }
  Self inv() const { return pow(MOD - 2); }
  Self& operator=(const Self& rh) {
    m_value = rh.m_value;
    return *this;
  }
  Self operator-() const { return Self(-m_value); }
  Self operator+(const Self& other) const {
    return Self(m_value + other.m_value);
  }
  Self operator-(const Self& other) const {
    return Self(m_value - other.m_value);
  }
  Self operator*(const Self& other) const {
    return Self(m_value * other.m_value);
  }
  Self operator/(const Self& other) const { return (*this) * other.inv(); }
  Self& operator+=(const Self& rh) { return (*this) = (*this) + rh; }
  Self& operator-=(const Self& rh) { return (*this) = (*this) - rh; }
  Self& operator*=(const Self& rh) { return (*this) = (*this) * rh; }
  int64_t value() const { return m_value; }
};

class BinaryIndexedTree {
  vector<int64_t> container;

 public:
  BinaryIndexedTree(size_t size) : container(size + 1) {
    fill(container.begin(), container.end(), 0);
  }
  void add(size_t i, int64_t v) {
    size_t idx = i + 1;
    while (idx < container.size()) {
      container[idx] += v;
      idx += idx & -idx;
    }
  }
  int64_t find(size_t i) {
    size_t idx = i;

    int64_t result = 0;
    while (idx != 0) {
      result = container[idx] + result;
      idx -= idx & -idx;
    }
    return result;
  }
  size_t lower_bound(int64_t v) {
    if (v == 0) {
      return 0;
    }
    int64_t w = v;
    size_t x = 0;
    for (size_t k = msb(container.size() - 1); k > 0; k >>= 1) {
      if (x + k < container.size() && container[x + k] < w) {
        w -= container[x + k];
        x += k;
      }
    }
    return x + 1;
  }

 private:
  size_t msb(size_t x) {
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return (x + 1) >> 1;
  }
};

using Mint = Modint<998244353>;

int main() {
  int N;
  cin >> N;

  using P = pair<int, int>;
  vector<P> p;
  vector<int> xq, yq;
  rep(i, N) {
    int x, y;
    cin >> x >> y;
    xq.push_back(x);
    yq.push_back(y);
    p.push_back(P(x, y));
  }

  sort(xq.begin(), xq.end());
  sort(yq.begin(), yq.end());
  rep(i, N) {
    int x, y;
    tie(x, y) = p[i];
    x = lower_bound(xq.begin(), xq.end(), x) - xq.begin();
    y = lower_bound(yq.begin(), yq.end(), y) - yq.begin();

    p[i] = P(x, y);
  }
  sort(p.begin(), p.end());

  vector<int> dl(N), dr(N), ul(N), ur(N);
  BinaryIndexedTree bit(N), rbit(N);
  rep(i, N) {
    int x, y;
    tie(x, y) = p[i];

    dl[i] = bit.find(y);
    ul[i] = i - dl[i];
    bit.add(y, 1);
  }

  rrep(i, N) {
    int x, y;
    tie(x, y) = p[i];

    dr[i] = rbit.find(y);
    ur[i] = (N - 1 - i) - dr[i];
    rbit.add(y, 1);
  }

  Mint result = 0;
  rep(i, N) {
    int x, y;
    tie(x, y) = p[i];

    const Mint m2 = 2;
    Mint score = m2.pow(N);
    score -= m2.pow(x) + m2.pow(N - x - 1) + m2.pow(y) + m2.pow(N - y - 1);
    score += m2.pow(dl[i]) + m2.pow(dr[i]) + m2.pow(ul[i]) + m2.pow(ur[i]) + 2;
    score -= 4;
    score += 1;

    result += score;
  }
  cout << result.value() << endl;

  return 0;
}

Measured memory_bytes: 9692