Problem:
Score : 600 points

Problem Statement

We have a set S of N points in a two-dimensional plane. The coordinates of the i-th point are (x_i, y_i). The N points have distinct x-coordinates and distinct y-coordinates.

For a non-empty subset T of S, let f(T) be the number of points contained in the smallest rectangle, whose sides are parallel to the coordinate axes, that contains all the points in T. More formally, we define f(T) as follows:

f(T) := (the number of integers i (1 \leq i \leq N) such that a \leq x_i \leq b and c \leq y_i \leq d, where a, b, c, and d are the minimum x-coordinate, the maximum x-coordinate, the minimum y-coordinate, and the maximum y-coordinate of the points in T)

Find the sum of f(T) over all non-empty subset T of S. Since it can be enormous, print the sum modulo 998244353.

Constraints

1 \leq N \leq 2 \times 10^5

-10^9 \leq x_i, y_i \leq 10^9

x_i \neq x_j (i \neq j)

y_i \neq y_j (i \neq j)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
:
x_N y_N

Output

Print the sum of f(T) over all non-empty subset T of S, modulo 998244353.

Sample Input 1

3
-1 3
2 1
3 -2

Sample Output 1

13

Let the first, second, and third points be P_1, P_2, and P_3, respectively. S = \{P_1, P_2, P_3\} has seven non-empty subsets, and f has the following values for each of them:

f(\{P_1\}) = 1

f(\{P_2\}) = 1

f(\{P_3\}) = 1

f(\{P_1, P_2\}) = 2

f(\{P_2, P_3\}) = 2

f(\{P_3, P_1\}) = 3

f(\{P_1, P_2, P_3\}) = 3

The sum of these is 13.

Sample Input 2

4
1 4
2 1
3 3
4 2

Sample Output 2

34

Sample Input 3

10
19 -11
-3 -12
5 3
3 -15
8 -14
-9 -20
10 -9
0 2
-7 17
6 -6

Sample Output 3

7222

Be sure to print the sum modulo 998244353.

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

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

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

using namespace std;

template <class T>
struct segment_tree {
  vector<T> data;
  T default_value;

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

  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] = data[l_child] + data[r_child]; //TODO: 親の計算方法もコンストラクタで渡したい
    }
  }

  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 _get(l, r, l_child, il, mid_bound) + //TODO: 親の計算方法もコンストラクタで渡したい
      _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計算クラス
// TODO: modの"数"を型にできるか？
template <class T>
struct calc_mod {
  T n;
  T mod;

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

  calc_mod operator+(calc_mod other) {
    return *this + other.n;
  }

  calc_mod operator+(T other) {
    return calc_mod((this->n + other) % this->mod, this->mod);
  }

  void operator+=(calc_mod other) {
    this->n += other.n;
  }

  void operator+=(T other) {
    this->n += other;
  }

  calc_mod operator-(calc_mod other) {
    return *this - other.n;
  }

  calc_mod operator-(T other) {
    return calc_mod((this->n - other + this->mod) % this->mod, this->mod);
  }

  calc_mod operator*(calc_mod other) {
    return *this * other.n;
  }

  calc_mod operator*(T other) {
    return calc_mod(this->n * other % this->mod, this->mod);
  }

  void operator*=(calc_mod other) {
    this->n *= other.n;
  }

  void operator*=(T other) {
    this->n *= other;
  }

  calc_mod operator/(calc_mod other) {
    return *this / other.n;
  }

  calc_mod operator/(T other) {
    return calc_mod(this->n / other, this->mod);
  }

  void operator/=(T other) {
    this->n /= other;
  }

  calc_mod operator%(calc_mod other) {
    return *this % other.n;
  }

  calc_mod operator%(T other) {
    return calc_mod(this->n % other, this->mod);
  }

  bool operator==(T other) {
    return this->n == other;
  }

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

  bool operator>(T other) {
    return this->n > other;
  }

  calc_mod pow(calc_mod other) {
    return this->pow(other.n);
  }
  calc_mod pow(T other) {
    calc_mod result(1, this->mod);
    calc_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>
calc_mod<T> case_count(calc_mod<T> points) {
  return (calc_mod<T>(2, MOD).pow(points)) - 1;
}

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;
  }

  calc_mod<unsigned long long> result(0, MOD);
  segment_tree<int> point_count_from_left(n, 0);
  segment_tree<int> point_count_from_right(n, 0);
  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象限に点がある場合
    calc_mod<unsigned long long> c1 = calc_mod<unsigned long long>(point_count[i][1], MOD);
    calc_mod<unsigned long long> c2 = calc_mod<unsigned long long>(point_count[i][2], MOD);
    calc_mod<unsigned long long> c3 = calc_mod<unsigned long long>(point_count[i][3], MOD);
    calc_mod<unsigned long long> c4 = calc_mod<unsigned long long>(point_count[i][4], MOD);

    // 点が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 += calc_mod<unsigned long long>(2, MOD).pow(n-1);
  }

  cout << result.n << endl;

  return 0;
}