#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i=0; i<(int)(n); ++i)
#define rep0(i,n) for (int i=0; i<=(int)(n); ++i)
#define rep1(i,n) for (int i=1; i<=(int)(n); ++i)
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using Graph = vector<vi>;  // vi <=> vl
using vb = vector<bool>;
using boolGraph = vector<vb>;
using P = pair<int, int>;  // int <=> ll
const int MOD = 1e9+7;
const int MOD2 = 998244353;
const double EPS = 1e-9;

template<typename T>
struct is_vector : false_type{};

template<typename T>
struct is_vector<vector<T>> : true_type{};

template<typename T>
ostream &operator << (ostream &ostr, const vector<T> &vec) {
  if (vec.empty()) {
    return ostr;
  }
  ostr << vec.front();
  for (auto itr = ++vec.begin(); itr != vec.end(); ++itr) {
    if (is_vector<T>()) ostr << "\n" << *itr;
    else ostr << ' ' << *itr;
  }
  return ostr;
}

template<typename T>
bool CompareBySecond(pair<T, T> a, pair<T, T> b) {
  if (a.second != b.second) {
    return a.second < b.second;
  } else {
    return a.first < b.first;
  }
}

template<typename Monoid>
struct SegmentTree {
  using F = function<Monoid(Monoid, Monoid)>;

  int sz;
  vector<Monoid> seg;

  const F f;
  const Monoid M1;

  SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while (sz < n) sz <<= 1;
    seg.assign(2*sz, M1);
  }

  void set(int k, const Monoid &x) {
    seg[k+sz] = x;
  }

  void build() {
    for (int k = sz-1; k>0; --k) {
      seg[k] = f(seg[2*k+0], seg[2*k+1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while (k >>= 1) {
      seg[k] = f(seg[2*k+0], seg[2*k+1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1) L = f(L, seg[a++]);
      if (b & 1) R = f(seg[--b], R);
    }
    return f(L, R);
  }
};

struct modpow {
  const int a;
  const int LOG;
  const int mod;
  vector<long long> table;

  modpow(const int a, const int &mod) : a(a), LOG(64), mod(mod), table(64) {
    table[0] = a;
    for (int i=1; i<LOG; ++i) {
      table[i] = table[i-1] * table[i-1] % mod;
    }
  }

  long long value(long long n) {
    if (n < 0) return 0;
    long long ret = 1;
    for (int i=0; i<LOG; ++i) {
      if ((n>>i) & 1) {
        (ret *= table[i]) %= mod;
      }
    }
    return ret;
  }
};

struct position {
  int ld, lu, rd, ru;
  position() {
    ld = lu = rd = ru = 0;
  }
};

void solve() {
  int n; cin >> n;
  vector<P> g(n);
  rep(i,n) {
    int x, y; cin >> x >> y;
    g[i] = P(x, y);
  }

  sort(ALL(g), CompareBySecond<int>);
  rep(i,n) g[i].second = i;

  sort(ALL(g));

  vector<position> pos(n);
  SegmentTree<ll> seg(n, [](ll a, ll b) { return a + b; }, 0);
  rep(i,n) {
    pos[i].ld = seg.query(0, g[i].second);
    pos[i].lu = i - pos[i].ld;
    seg.update(g[i].second, 1);
  }
  rep(i,n) {
    pos[i].rd = seg.query(0, g[i].second) - pos[i].ld;
    pos[i].ru = n-1 - i - pos[i].rd;
  }

  modpow mp(2, MOD2);
  ll ans = mp.value(n-1) * n % MOD2;
  rep(i,n) {
    ll ld = mp.value(pos[i].ld) - 1;
    ll lu = mp.value(pos[i].lu) - 1;
    ll rd = mp.value(pos[i].rd) - 1;
    ll ru = mp.value(pos[i].ru) - 1;
    ll ld_ru = ld * ru % MOD2;
    ll lu_rd = lu * rd % MOD2;
    (ans += ld_ru * (1 + lu + rd)) %= MOD2;
    (ans += lu_rd * (1 + ld + ru)) %= MOD2;
    (ans += ld_ru * lu_rd) %= MOD2;
  }

  cout << ans << endl;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  solve();
  return 0;
}


Measured memory_bytes: 9088