#include<vector>
#include<unordered_map>
#include<algorithm>
using Size = int;
template<typename T> class Compression {
 public:
  Compression(const std::vector<T>& list) : value_(list) {
    std::sort(begin(value_), end(value_));
    value_.erase(std::unique(begin(value_), end(value_)), end(value_));
    for(Size i = 0; i < value_.size(); ++i) index_[value_[i]] = i;
  }
  Size size() const {return value_.size();}
  Size index(const T& v) const {return index_.at(v);}
  T operator[](const Size i) const {return value_.at(i);}
 private:
  std::unordered_map<T, Size> index_;
  std::vector<T> value_;
};

#include<vector>
template<typename T> class SegmentTree {
 public:
  SegmentTree(int n) : n(size(n)), dat(size(n) << 1), laz(size(n) << 1) {}
  void add(int a, int b, T v) {add(a, b, v, 1, 0, n);}
  T sum(int a, int b) {return sum(a, b, 1, 0, n);}
 private:
  constexpr int size(int n) const {return n & (n - 1) ? size(n + (n & -n)) : n;}
  inline int lchild(int k) const {return (k << 1);}
  inline int rchild(int k) const {return (k << 1) | 1;}
  inline void propagate(int k, int l, int r) {
    if(k < n) {
      laz[lchild(k)] += laz[k];
      laz[rchild(k)] += laz[k];
    }
    dat[k] += (r - l) * laz[k];
    laz[k] = 0;
  }
  T add(int a, int b, T v, int k, int l, int r) {
    propagate(k, l, r);
    if(b <= l || r <= a) return dat[k];
    if(a <= l && r <= b) return dat[k] + (r - l) * (laz[k] = v);
    auto m = (l + r) >> 1;
    auto vl = add(a, b, v, lchild(k), l, m);
    auto vr = add(a, b, v, rchild(k), m, r);
    return dat[k] = vl + vr;
  }
  T sum(int a, int b, int k, int l, int r) {
    propagate(k, l, r);
    if(b <= l || r <= a) return 0;
    if(a <= l && r <= b) return dat[k];
    auto m = (l + r) >> 1;
    auto vl = sum(a, b, lchild(k), l, m);
    auto vr = sum(a, b, rchild(k), m, r);
    return vl + vr;
  }
  int n;
  std::vector<T> dat, laz;
};

#include<bits/stdc++.h>
using namespace std;

using LL = long long;

const LL M = 998244353;
const LL INF = 1e9+1;

LL power(LL m, LL n) {
  if(!n) return 1;
  return (n & 1) ? (power(m, n - 1) * m % M) : power(m * m % M, n >> 1);
}

int main() {
  struct Point {LL x, y, ul, ur, ll, lr;};
  int N;
  cin >> N;
  vector<Point> P(N);
  for(auto& i: P) cin >> i.x >> i.y;

  vector<int> v = {-INF, INF};
  for(auto& p: P) v.emplace_back(p.x), v.emplace_back(p.y);
  Compression C(v);

  sort(begin(P), end(P), [](auto& l, auto& r){
    if(l.x != r.x) return l.x < r.x;
    return l.y < r.y;
  });
  SegmentTree<int> rsq(C.size());
  for(auto& p: P) {
    p.ll = rsq.sum(C.index(-INF),  C.index(p.y)+1);
    p.ul = rsq.sum(C.index(p.y)+1, C.index(INF));
    rsq.add(C.index(p.y), C.index(p.y)+1, 1);
  }

  sort(begin(P), end(P), [](auto& l, auto& r){
    if(l.x != r.x) return l.x > r.x;
    return l.y > r.y;
  });
  rsq = SegmentTree<int>(C.size());
  for(auto& p: P) {
    p.ur = rsq.sum(C.index(p.y),  C.index(INF));
    p.lr = rsq.sum(C.index(-INF), C.index(p.y));
    rsq.add(C.index(p.y), C.index(p.y)+1, 1);
  }

  LL ans = 0;
  for(auto& p: P) {
    (ans += power(2,N-1)) %= M;
    auto urll = (power(2,p.ur)-1) * (power(2,p.ll)-1) % M;
    auto ullr = (power(2,p.ul)-1) * (power(2,p.lr)-1) % M;
    (ans += urll * power(2,N-1-p.ur-p.ll) % M) %= M;
    (ans += ullr * power(2,N-1-p.ul-p.lr) % M) %= M;
    (ans += M - (urll*ullr%M) * power(2,N-1-p.ur-p.ll-p.ul-p.lr)%M) %= M;
  }
  cout << ans << endl;
}


Measured memory_bytes: 48860