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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using static Assistant.Input;
using static Assistant.Debug;
using System.Linq;
using Assistant;

namespace ABC136F
{
    class Program
    {
        static void Main(string[] args)
        {
            int N = ReadInt;
            long mod = 998244353;

            //int[,] a = new int[200000, 200000];
            //long[,] b = new long[200000, 200000];

            int[] x = new int[N];
            int[] y = new int[N];
            for (int i = 0; i < N; i++)
            {
                x[i] = ReadInt;
                y[i] = ReadInt;
            }

            //座標圧縮
            var toValueX = x.Distinct().OrderBy(v => v).ToArray();
            var toValueY = y.Distinct().OrderBy(v => v).ToArray();

            var indexFromValueTableX = toValueX.Select((value, index) => new { value, index }).ToDictionary(p => p.value, p => p.index);
            var indexFromValueTableY = toValueY.Select((value, index) => new { value, index }).ToDictionary(p => p.value, p => p.index);

            int countX = indexFromValueTableX.Count;
            int countY = indexFromValueTableY.Count;

            x = x.Select(v => indexFromValueTableX[v]).ToArray();
            y = y.Select(v => indexFromValueTableY[v]).ToArray();

            //x順にソート
            Point[] points = new Point[N];
            for (int i = 0; i < N; i++)
            {
                points[i] = new Point() { x = x[i], y = y[i] };
            }
            points = points.OrderBy(a => a.x).ToArray();
            for (int i = 0; i < N; i++)
            {
                x[i] = points[i].x;
                y[i] = points[i].y;
            }

            //二次元累積和
            //int[,] comb = new int[N + 1, N + 1];
            //for (int i = 0; i < N; i++)
            //{
            //    comb[x[i] + 1, y[i] + 1] = 1;
            //}

            ////O(n^2)
            //for (int i = 0; i < N; i++)
            //{
            //    for (int j = 0; j < N; j++)
            //    {
            //        comb[i + 1, j + 1] += comb[i + 1, j] + comb[i, j + 1] - comb[i, j];
            //    }
            //}

            //DrawMapforDebug(comb);

            //BIT2d 二次元bitはメモリオーバー
            //BIT2D bit2D = new BIT2D(N + 1, N + 1);
            //for (int i = 0; i < N; i++)
            //{
            //    bit2D.Add(x[i] + 1, y[i] + 1, 1);
            //}
            //bit2D.DrawBit2D(2);

            //1次元bit二つ
            BIT bitL = new BIT(N);
            BIT bitR = new BIT(N);
            for (int i = 0; i < N; i++)
            {
                bitR.Add(y[i] + 1, y[i] + 1, 1);
            }

            //各星について総数を求める.
            long ans = 0;
            long all = ModPow(2, N, mod);
            for (int i = 0; i < N; i++)
            {
                //TLE予定
                //int c1 = comb[N, N] - comb[N, y[i] + 1] - comb[x[i] + 1, N] + comb[x[i] + 1, y[i] + 1];
                //int c2 = comb[x[i], N] - comb[x[i], y[i]];
                //int c3 = comb[x[i], y[i]];
                //int c4 = comb[N, y[i]] - comb[x[i], y[i]];

                //高速化
                //long c1 = bit2D.Query(x[i] + 2, y[i] + 2, N, N);
                //long c2 = bit2D.Query(1, y[i] + 2, x[i], N);
                //long c3 = bit2D.Query(1, 1, x[i], y[i]);
                //long c4 = bit2D.Query(x[i] + 1, 1, N, y[i]);

                //スライド式
                long c1 = bitR.Sum(y[i] + 2, N);
                long c2 = bitL.Sum(y[i] + 2, N);
                long c3 = bitL.Sum(1, y[i]);
                long c4 = bitR.Sum(1, y[i]);

                long powRU = ModPow(2, c1, mod);
                long powLU = ModPow(2, c2, mod);
                long powLD = ModPow(2, c3, mod);
                long powRD = ModPow(2, c4, mod);

                long powU = ModPow(2, c1 + c2, mod);
                long powL = ModPow(2, c2 + c3, mod);
                long powD = ModPow(2, c3 + c4, mod);
                long powR = ModPow(2, c4 + c1, mod);

                long sum = (all + powRU + powLU + powLD + powRD - powU - powL - powD - powR - 1 + mod) % mod;

                ans = (ans + sum) % mod;

                bitL.Add(y[i] + 1, y[i] + 1, 1);
                bitR.Add(y[i] + 1, y[i] + 1, -1);
            }

            Console.WriteLine(ans);
        }

        struct Point
        {
            public int x;
            public int y;
        }

        /// <summary>
        /// a^n (mod p)
        /// nが非常に大きい時に有効
        /// </summary>
        /// <param name="a"></param>
        /// <param name="n"></param>
        /// <param name="mod"></param>
        /// <returns></returns>
        public static long ModPow(long a, long n, long p)
        {
            if (n == 0) return 1;
            if (n == 1) return a % p;
            if (n % 2 == 1) return (a * ModPow(a, n - 1, p)) % p;

            long t = ModPow(a, n / 2, p);
            return (t * t) % p;
        }
    }

    class BIT
    {
        long[] bit0, bit1;  //1-indexed
        int n;
        public BIT(int n)
        {
            bit0 = new long[n + 1];
            bit1 = new long[n + 1];
            this.n = n;
        }

        public long Sum(int l, int r)
        {
            long ret = 0;
            ret += Sum(bit0, r) + Sum(bit1, r) * r;
            ret -= Sum(bit0, l - 1) + Sum(bit1, l - 1) * (l - 1);
            return ret;
        }

        long Sum(long[] bit, int i)
        {
            long s = 0;
            while (i > 0)
            {
                s += bit[i];
                i -= i & -i;
            }
            return s;
        }

        public void Add(int l, int r, int a)
        {
            Add(bit0, l, -a * (l - 1));
            Add(bit1, l, a);
            Add(bit0, r + 1, a * r);
            Add(bit1, r + 1, -a);
        }

        void Add(long[] bit, int i, int a)
        {
            while (i <= n)
            {
                bit[i] += a;
                i += i & -i;
            }
        }
    }

    class BIT2D
    {
        int H, W;
        int[,] bit;
        public BIT2D(int H_, int W_) { Init(H_, W_); }
        void Init(int H_, int W_)
        {
            H = H_ + 1;
            W = W_ + 1;

            bit = new int[H, W];
        }

        public void Add(int h, int w, int x)
        {
            for (int i = h; i < H; i += (i & -i))
            {
                for (int j = w; j < W; j += (j & -j))
                {
                    bit[i, j] += x;
                }
            }
        }
        // 1≦i≦h かつ 1≦j≦w
        public long Sum(int h, int w)
        {
            long s = 0;
            for (int i = h; i > 0; i -= (i & -i))
            {
                for (int j = w; j > 0; j -= (j & -j))
                {
                    s += bit[i, j];
                }
            }
            return s;
        }

        // h1≦i<h2 かつ w1≦j<w2
        public long Query(int h1, int w1, int h2, int w2)
        {
            return Sum(h2, w2) - Sum(h2, w1 - 1) - Sum(h1 - 1, w2) + Sum(h1 - 1, w1 - 1);
        }

        public void DrawBit2D(int mode = 0)
        {
            for (int i = 1; i < H; i++)
            {
                for (int j = 1; j < W; j++)
                {
                    if (mode == 0) Console.Write(Sum(i, j) + " ");
                    if (mode == 2) Console.Write(Query(i - 1, j - 1, i, j) + " ");
                }
                Console.WriteLine();
            }
        }
    }
}

namespace Assistant
{
    static class Input
    {
        static List<string> line = new List<string>();
        static int index = 0;
        static String ReadNext()
        {
            if (line.Count <= index) line.AddRange(Console.ReadLine().Split());
            return line[index++];
        }
        public static int ReadInt => int.Parse(ReadNext());
        public static long ReadLong => long.Parse(ReadNext());
        public static int[] ReadInts => Console.ReadLine().Split().Select(int.Parse).ToArray();
        public static long[] NextLongs => Console.ReadLine().Split().Select(long.Parse).ToArray();
    }

    static class Debug
    {
        //drawmap
        //drawarray
        /// <summary>
        /// 二次元配列の可視化メソッド
        /// </summary>
        /// <param name="map"></param>
        static public void DrawMapforDebug(int[,] map, int mode = 1)
        {
            int W = map.GetLength(0);
            int H = map.GetLength(1);

            int[,] map2 = new int[W + 1, H + 1];
            for (int i = 0; i < W + 1; i++)
            {
                for (int j = 0; j < H + 1; j++)
                {
                    if (i == 0 && j == 0) map2[i, j] = 0;
                    else if (i == 0) map2[i, j] = j - 1;
                    else if (j == 0) map2[i, j] = i - 1;
                    else map2[i, j] = map[i - 1, j - 1];
                }
            }

            for (int i = 0; i < W + 1; i++)
            {
                for (int j = 0; j < H + 1; j++)
                {
                    if (mode == 0) Console.Write(map2[i, j] % 10);
                    if (mode == 1) Console.Write(map2[i, j] + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
}