#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<unordered_map>
#include<stack>
#include<string>
#include<algorithm>
#include<functional>
#include<cstring>
#include<complex>
#include<bitset>
#include<iostream>
using namespace std;
typedef long long ll;

template <typename T>
class Zip {
  vector<T> d;
  bool flag;
public:
  Zip() {
    flag = false;
  }
  void add(T x) {
    d.push_back(x);
    flag = true;
  }
  ll getNum(T x) { // T need to have operator < !!
    if (flag) {
      sort(d.begin(), d.end());
      d.erase(unique(d.begin(), d.end()), d.end());
      flag = false;
    }
    return lower_bound(d.begin(), d.end(), x) - d.begin();
  }
  ll size() {
    if (flag) {
      sort(d.begin(), d.end());
      d.erase(unique(d.begin(), d.end()), d.end());
      flag = false;
    }
    return (ll)d.size();
  }
};

template <typename T>
class SegmentTree {
  ll n;
  vector<T> node;
  function<T(T, T)> fun, fun2;
  bool customChange;
  T outValue, initValue;
public:
  void init(ll num, function<T(T, T)> resultFunction, T init, T out, function<T(T, T)> changeFunction = NULL) {
    // changeFunction: (input, beforevalue) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    customChange = changeFunction != NULL;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1, init);
    outValue = out;
    initValue = init;
  }
  void valueChange(ll num, T value) {
    num += n-1;
    if (customChange) node[num] = fun2(value, node[num]);
    else node[num] = value;
    while (num > 0) num = (num - 1) / 2, node[num] = fun(node[num * 2 + 1], node[num * 2 + 2]);
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (a <= l && r <= b) return node[k];
    if (b <= l || r <= a) return outValue;
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

template <typename T>
T sum(T a, T b) { return a + b; }

template <typename T>
class ZipSegment {
  Zip<T> zip;
  SegmentTree<ll> sgt;
public:
  ll counter;
  void add(T x) {
    zip.add(x);
  }
  void init() {
    sgt.init(zip.size() + 10, sum<ll>, 0, 0, sum<T>);
    counter = 0;
  }
  ll getNum(T a) {
    // first .. a (num)
    return sgt.rangeQuery(0, zip.getNum(a) + 1);
  }
  void change(T a, ll x) {
    // a -> +x
    sgt.valueChange(zip.getNum(a), x);
    counter += x;
  }
};

ll n, x[200000], y[200000], pow2[200001], ans;
const ll mod = 998244353;
typedef pair<ll, ll> P;
P p[200000];
ZipSegment<ll> zy, zy2;

int main() {
  scanf("%lld", &n);
  pow2[0] = 1;
  for (ll i = 0; i < n; i++) pow2[i+1] = (pow2[i] * 2) % mod;
  for (ll i = 0; i < n; i++) scanf("%lld%lld", &x[i], &y[i]), p[i] = P(x[i], y[i]), zy.add(y[i]), zy2.add(y[i]);
  zy.init(); zy2.init();
  for (ll i = 0; i < n; i++) zy.change(y[i], 1);
  sort(p, p+n);
  for (ll i = 0; i < n; i++) {
    zy.change(p[i].second, -1);
    ll a = zy.getNum(p[i].second), c = zy.counter - a;
    ll b = zy2.getNum(p[i].second), d = zy2.counter - b;
    ans = (ans + pow2[n] - pow2[a+b] - pow2[b+d] - pow2[d+c] - pow2[c+a]
               + pow2[a] + pow2[b] + pow2[c] + pow2[d] - 1) % mod;
    zy2.change(p[i].second, 1);
  }
  ans = (ans + mod) % mod;
  printf("%lld\n", ans);
}


Measured memory_bytes: 19556