/*
 * 解説の方法を試す
 * セグメントツリーを使って、点pから見た4象限の点数を計算する
 */

#include <iostream>
#include <unordered_map>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <functional>

using namespace std;

template <class T>
struct segment_tree {
  vector<T> data;
  T default_value;
  function<T(T, T)> plus;

  segment_tree(int size, T default_value, function<T(T, T)> plus ) { //default_valueと親にまとめる演算子を持つので、実はモノイドを要素にしている
    int n = 2 * pow(2, ceil(log2(size))) - 1;
    data.assign(n, default_value);
    this->default_value = default_value;
    this->plus = plus;
  }

  int leaf_size() {
    return (data.size() + 1) / 2;
  }

  int not_leaf_size() {
    return leaf_size() - 1;
  }

  void set(int n, T value) {
    int i = not_leaf_size() + n;
    data[i] = value;

    while (i > 0) {
      i = (i-1)/2;
      int l_child = 2*i+1;
      int r_child = 2*i+2;
      data[i] = plus(data[l_child], data[r_child]);
    }
  }

  int get(int l, int r) {
    return _get(l, r, 0, 0, leaf_size() - 1);
  }

  int _get(int l, int r, int i, int il, int ir) {
    if (r < il || ir < l) {
      return default_value;
    }
    if (l <= il && ir <= r) {
      return data[i];
    }

    int l_child = 2*i+1;
    int r_child = 2*i+2;
    int mid_bound = (il + ir + 1)/2 - 1;

    return plus(
        _get(l, r, l_child, il, mid_bound),
        _get(l, r, r_child, mid_bound + 1, ir));
  }

  void dump() {
    int row_count = 1;
    for (int row = 0; row < data.size(); row++) {
      cout << data[row] << " ";

      if (row_count == row + 1) {
        cout << endl;
        row_count = row_count * 2 + 1;
      }
    }
  }
};

struct point {
  int x;
  int y;
};

// mod計算クラス
template <class T, T mod>
struct calc_mod {
  T n;

  calc_mod(T n) {
    this->n = n;
  }

  T plus(T a, T b) { return (a + b) % mod; }
  calc_mod<T, mod> operator+(calc_mod<T, mod> other) { return plus(this->n, other.n); }
  calc_mod<T, mod> operator+(T other) { return calc_mod<T, mod>(plus(this->n, other)); }
  void operator+=(calc_mod<T, mod> other) { this->n = plus(this->n, other.n); }
  void operator+=(T other) { this->n = plus(this->n, other.n); }

  T sub(T a, T b) { return (a - b + mod) % mod; }
  calc_mod<T, mod> operator-(calc_mod<T, mod> other) { return sub(this->n, other.n); }
  calc_mod<T, mod> operator-(T other) { return calc_mod<T, mod>(sub(this->n, other)); }
  void operator-=(calc_mod<T, mod> other) { this->n = sub(this->n, other.n); }
  void operator-=(T other) { this->n = sub(this->n + other.n); }

  T multi(T a, T b) { return (a * b) % mod; }
  calc_mod<T, mod> operator*(calc_mod<T, mod> other) { return multi(this->n, other.n); }
  calc_mod<T, mod> operator*(T other) { return calc_mod<T, mod>(multi(this->n, other)); }
  void operator*=(calc_mod<T, mod> other) { this->n = multi(this->n, other.n); }
  void operator*=(T other) { this->n = multi(this->n + other.n); }

  T div(T a, T b) { return a / b; }
  calc_mod<T, mod> operator/(calc_mod<T, mod> other) { return div(this->n, other.n); }
  calc_mod<T, mod> operator/(T other) { return calc_mod<T, mod>(div(this->n, other)); }
  void operator/=(calc_mod<T, mod> other) { this->n = div(this->n, other.n); }
  void operator/=(T other) { this->n = div(this->n + other.n); }

  T modu(T a, T b) { return a % b; }
  calc_mod<T, mod> operator%(calc_mod<T, mod> other) { return modu(this->n, other.n); }
  calc_mod<T, mod> operator%(T other) { return calc_mod<T, mod>(modu(this->n, other)); }
  void operator%=(calc_mod<T, mod> other) { this->n = modu(this->n, other.n); }
  void operator%=(T other) { this->n = modu(this->n + other.n); }

  //TODO: このあたり、haskellのeqみたいに定義できないか？
  bool operator==(calc_mod<T, mod> other) { return this->n == other.n; }
  bool operator==(T other) { return this->n == other; }
  bool operator!=(calc_mod<T, mod> other) { return this->n != other.n; }
  bool operator!=(T other) { return this->n != other; }

  bool operator>(calc_mod<T, mod> other) { return this->n > other.n; }
  bool operator>(T other) { return this->n > other; }
  bool operator>=(calc_mod<T, mod> other) { return this->n >= other.n; }
  bool operator>=(T other) { return this->n >= other; }
  bool operator<(calc_mod<T, mod> other) { return this->n < other.n; }
  bool operator<(T other) { return this->n < other; }
  bool operator<=(calc_mod<T, mod> other) { return this->n <= other.n; }
  bool operator<=(T other) { return this->n <= other; }

  calc_mod<T, mod> pow(calc_mod<T, mod> other) {
    return this->pow(other.n);
  }
  calc_mod<T, mod> pow(T other) {
    // 累乗は繰り返し自乗法で
    calc_mod<T, mod> result(1);
    calc_mod<T, mod> x = *this;
    T b = other;

    for (;b > 0;b /= 2) {
      if (b%2 == 1) {
        result *= x;
      }

      x *= x;
    }

    return result;
  }
};

const int MOD = 998244353;

template <class T, T mod>
calc_mod<T, mod> case_count(calc_mod<T, mod> points) {
  return (calc_mod<T, mod>(2).pow(points)) - 1;
}

// 数値も型(テンプレート)引数にできる
using modtype = calc_mod<unsigned long long, MOD>;

int main() {

  int n;
  cin >> n;
  vector<point> points(n);

  int x,y;
  for (int i = 0; i < n; i++) {
    cin >> x >> y;
    points[i] = {x, y};
  }

  // yを0からの連番に置換。セグメントツリーが大きくならないように
  sort(points.begin(), points.end(), [](point a, point b){return a.y < b.y;});
  for (int i = 0; i < n; i++) {
    points[i].y = i;
  }

  modtype result(0);
  auto plus = [](int a, int b){return a+b;};
  segment_tree<int> point_count_from_left(n, 0, plus);
  segment_tree<int> point_count_from_right(n, 0, plus);
  vector<vector<int>> point_count(n, vector<int>(5)); // 点pから見た、第n象限の点数

  // x軸左から
  sort(points.begin(), points.end(), [](point a, point b){return a.x < b.x;});
  for (int i = 0; i < n; i++) {
    point p = points[i];

    point_count[i][3] = point_count_from_left.get(0, p.y);
    point_count[i][2] = point_count_from_left.get(p.y, n);

    point_count_from_left.set(p.y, 1);
  }

  // x軸右から
  for (int i = n-1; i >= 0; i--) {
    point p = points[i];

    point_count[i][4] = point_count_from_right.get(0, p.y);
    point_count[i][1] = point_count_from_right.get(p.y, n);

    point_count_from_right.set(p.y, 1);
  }

  // 各点ごとに計算
  for (int i = 0; i < n; i++) {
    // 1.
    // 自分が部分集合に入っていないのに内部に含まれるのは、点pから見て第2・4象限に点がある場合と、第1・3象限に点がある場合
    modtype c1(point_count[i][1]);
    modtype c2(point_count[i][2]);
    modtype c3(point_count[i][3]);
    modtype c4(point_count[i][4]);

    // 点が1以上ある場合の数は2**点数-1
    c1 = case_count(c1);
    c2 = case_count(c2);
    c3 = case_count(c3);
    c4 = case_count(c4);

    // 重複を避けるため、パターンごとに計算
    int inner_patterns[]{
      // 2象限のみにある場合
      0b1010,
      0b0101,
      // 3象限
      0b1110,
      0b1101,
      0b1011,
      0b0111,
      // 4象限
      0b1111
    };

    for (const auto& inner_pattern : inner_patterns) {
      result +=
        (c1.pow((inner_pattern >> 3) & 1)) *
        (c2.pow((inner_pattern >> 2) & 1)) *
        (c3.pow((inner_pattern >> 1) & 1)) *
        (c4.pow((inner_pattern >> 0) & 1));
    }

    // 2.
    // 部分集合に含まれるのは、2**n-1 (自分以外は含まれる/含まれないどちらでもいい)
    result += modtype(2).pow(n-1);
  }

  cout << result.n << endl;

  return 0;
}


Measured memory_bytes: 16896