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 Java8 (OpenJDK 1.8.0) (judge verdict: Runtime Error)

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.io.IOException;
import java.util.function.Function;
import java.util.List;
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.io.FileInputStream;
import java.io.InputStream;

public class Main {
    InputStream is;

    int __t__ = 1;
    int __f__ = 0;
    int __FILE_DEBUG_FLAG__ = __t__;
    String __DEBUG_FILE_NAME__ = "src/b25";

    FastScanner in;
    PrintWriter out;

    public void solve() {
        int n = in.nextInt();
        int[] x = new int[n];
        int[] y = new int[n];
        for (int i = 0; i < n; i++) {
            x[i] = in.nextInt();
            y[i] = in.nextInt();
        }
        x = ArrayLibs.compress(x);
        y = ArrayLibs.compress(y);

        Point[] ps = new Point[n];
        for (int i = 0; i < n; i++) {
            ps[i] = new Point(x[i], y[i]);
        }

        int[] upOnBorder = calcBorder(ps, Comparator.comparingInt(Point::getY), Point::getX);
        int[] downOnBorder = calcBorder(ps, Comparator.comparingInt(p -> -p.y), Point::getX);
        int[] leftOnBorder = calcBorder(ps, Comparator.comparingInt(Point::getX), Point::getY);
        int[] rightOnBorder = calcBorder(ps, Comparator.comparing(p -> -p.x), Point::getY);


    }

    private int[] calcBorder(final Point[] ps, final Comparator<Point> pointComparator, final Function<Point, Integer> getVal) {
        int n = ps.length;
        Arrays.sort(ps, pointComparator);
        int[] border = new int[n];
        int[] cnt = new int[n];
        for (int i = 0; i < n; i++) {
            int pos = getVal.apply(ps[i]);
            border[i] = cnt[pos];
            cnt[pos]++;
        }
        return border;
    }

    class Point {
        final int x;
        final int y;

        public Point(final int x, final int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }
    }

    public void run() {
        if (__FILE_DEBUG_FLAG__ == __t__) {
            try {
                is = new FileInputStream(__DEBUG_FILE_NAME__);
            } catch (FileNotFoundException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
            System.out.println("FILE_INPUT!");
        } else {
            is = System.in;
        }
        in = new FastScanner(is);
        out = new PrintWriter(System.out);

        solve();
    }

    public static void main(final String[] args) {
        new Main().run();
    }

}

class StringLibs {

    public static int[] kmp(String pattern) {
        int n = pattern.length();
        int[] table = new int[n + 1];
        table[0] = -1;
        int j = -1;
        for (int i = 0; i < pattern.length(); i++) {
            while (j >= 0 && pattern.charAt(i) != pattern.charAt(j)) j = table[j];
            j++;
            table[i + 1] = j;
        }
        return table;
    }

    public static int find(String target, String pattern) {
        int[] table = kmp(pattern);

        int n = target.length();
        int j = 0;
        for (int i = 0; i < n; i++) {
            while (j >= 0 && target.charAt(i) != pattern.charAt(j)) {
                j = table[j];
            }
            j++;
            if (j == pattern.length()) {
                return i + 1 - pattern.length();
            }
        }
        return -1;
    }


    public static int[] zAlgo(String s) {
        int n = s.length();
        int[] res = new int[n];
        res[0] = n;
        int i = 1, j = 0;
        while (i < n) {
            while (i + j < n && s.charAt(j) == s.charAt(i + j)) j++;
            res[i] = j;
            if (j == 0) {
                i++;
                continue;
            }

            int k = 1;
            while (i + k < n && k + res[k] < j) {
                res[i + k] = res[k];
                k++;
            }
            i += k;
            j -= k;
        }
        return res;
    }
}


class FastScanner {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;

    public FastScanner(InputStream stream) {
        this.stream = stream;
        // stream = new FileInputStream(new File("dec.in"));
    }

    int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public boolean isSpaceChar(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public boolean isEndline(int c) {
        return c == '\n' || c == '\r' || c == -1;
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public int[] nextIntArray(int n) {
        int[] array = new int[n];
        for (int i = 0; i < n; i++)
            array[i] = nextInt();

        return array;
    }

    public int[][] nextIntMap(int n, int m) {
        int[][] map = new int[n][m];
        for (int i = 0; i < n; i++) {
            map[i] = nextIntArray(m);
        }
        return map;
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

    public long[] nextLongArray(int n) {
        long[] array = new long[n];
        for (int i = 0; i < n; i++)
            array[i] = nextLong();

        return array;
    }

    public long[][] nextLongMap(int n, int m) {
        long[][] map = new long[n][m];
        for (int i = 0; i < n; i++) {
            map[i] = nextLongArray(m);
        }
        return map;
    }

    public double nextDouble() {
        return Double.parseDouble(next());
    }

    public double[] nextDoubleArray(int n) {
        double[] array = new double[n];
        for (int i = 0; i < n; i++)
            array[i] = nextDouble();

        return array;
    }

    public double[][] nextDoubleMap(int n, int m) {
        double[][] map = new double[n][m];
        for (int i = 0; i < n; i++) {
            map[i] = nextDoubleArray(m);
        }
        return map;
    }

    public String next() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));
        return res.toString();
    }

    public String[] nextStringArray(int n) {
        String[] array = new String[n];
        for (int i = 0; i < n; i++)
            array[i] = next();

        return array;
    }

    public String nextLine() {
        int c = read();
        while (isEndline(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isEndline(c));
        return res.toString();
    }

    public int[][] nextPackedIntArrays(int packN, int size) {
        int[][] res = new int[packN][size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < packN; j++) {
                res[j][i] = nextInt();
            }
        }
        return res;
    }
}


/**
 *
 */
class ArrayLibs {
    public static int[] compress(int[] x) {
        int n = x.length;
        int[] sorted = Arrays.copyOf(x, n);
        Arrays.sort(sorted);
        int[] uniq = ArrayLibs.unique(sorted);

        int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            res[i] = Arrays.binarySearch(uniq, x[i]);
        }
        return res;
    }

    private static int[] unique(final int[] sorted) {
        int cnt = 1;
        for (int i = 1; i < sorted.length; i++) {
            if (sorted[i] != sorted[i-1]) cnt++;
        }
        int[] res = new int[cnt];
        res[0] = sorted[0];
        for (int i = 1, cur = 1; i < sorted.length; i++) {
            if (sorted[i] != sorted[i-1]) {
                res[cur++] = sorted[i];
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int[] x = new int[]{20,30,10,10,30};
        System.out.println(Arrays.toString(compress(x)));
    }
}