Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Union of Rectangles

Given a set of $N$ axis-aligned rectangles in the plane, find the area of regions which are covered by at least one rectangle.

Input

The input is given in the following format.

$N$

$x1_1$ $y1_1$ $x2_1$ $y2_1$

$x1_2$ $y1_2$ $x2_2$ $y2_2$

:

$x1_N$ $y1_N$ $x2_N$ $y2_N$

($x1_i, y1_i$) and ($x2_i, y2_i$) are the coordinates of the top-left corner and the bottom-right corner of the $i$-th rectangle respectively.

Constraints

$ 1 \leq N \leq 2000 $

$ −10^9 \leq x1_i < x2_i\leq 10^9 $

$ −10^9 \leq y1_i < y2_i\leq 10^9 $

Output

Print the area of the regions.

Sample Input 1

2
0 0 3 4
1 2 4 3

Sample Output 1

13

Sample Input 2

3
1 1 2 5
2 1 5 2
1 2 2 5

Sample Output 2

7

Sample Input 3

4
0 0 3 1
0 0 1 3
0 2 3 3
2 0 3 3

Sample Output 3

8

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Pair = System.Collections.Generic.KeyValuePair<int, int>;

class Program
{
    static void Main()
    {
        var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
        Console.SetOut(sw);
        new Program().solve();
        Console.Out.Flush();
    }
    Scanner cin = new Scanner();

    int N;
    int[] x1, y1, x2, y2, XX, YY, Z;
    HashSet<int> X, Y;
    List<int>[] m1, m2;
    long ans;
    void solve()
    {
        N = cin.nextint;
        x1 = new int[N]; y1 = new int[N]; x2 = new int[N]; y2 = new int[N];
        X = new HashSet<int>(); Y = new HashSet<int>();
       
        for (int i = 0; i < N; i++)
        {
            x1[i] = cin.nextint; y1[i] = cin.nextint;
            x2[i] = cin.nextint; y2[i] = cin.nextint;
            X.Add(x1[i]); X.Add(x2[i]);
            Y.Add(y1[i]); Y.Add(y2[i]);
        }

        XX = X.OrderBy(x => x).ToArray();
        YY = Y.OrderBy(y => y).ToArray();
        m1 = Enumerable.Range(0, YY.Length).Select(i => new List<int>()).ToArray();
        m2 = Enumerable.Range(0, YY.Length).Select(i => new List<int>()).ToArray();

        for (int i = 0; i < N; i++)
        {
            x1[i] = LowerBound(XX, x1[i]); y1[i] = LowerBound(YY, y1[i]);
            x2[i] = LowerBound(XX, x2[i]); y2[i] = LowerBound(YY, y2[i]);
            m1[y1[i]].Add(i); m2[y2[i]].Add(i);
        }

        Z = new int[XX.Length - 1];

        for (int i = 0; i < YY.Length; i++)
        {
            if(i != 0)
            {
                long sum = 0;
                for (int j = 0; j < XX.Length - 1; j++)
                {
                    if (Z[j] != 0)
                    {
                        sum += XX[j + 1] - XX[j];
                    }
                }
                ans += sum * (YY[i] - YY[i - 1]);
            }
            foreach (var m in m1[i])
            {
                for (int j = x1[m]; j < x2[m]; j++)
                {
                    Z[j]++;
                }
            }
            foreach (var m in m2[i])
            {
                for (int j = x1[m]; j < x2[m]; j++)
                {
                    Z[j]--;
                }
            }
        }

        Console.WriteLine(ans);
    }


    int LowerBound(int[] arr, int val)
    {
        int low = 0, high = arr.Length;
        int mid;

        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid] < val) low = mid + 1;
            else high = mid;
        }
        return low;
    }
}

class Scanner
{
    string[] s; int i;
    char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] scan { get { return Console.ReadLine().Split(); } }
    public int[] scanint { get { return Array.ConvertAll(scan, int.Parse); } }
    public long[] scanlong { get { return Array.ConvertAll(scan, long.Parse); } }
    public double[] scandouble { get { return Array.ConvertAll(scan, double.Parse); } }
    public string next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return next;
        }
    }
    public int nextint { get { return int.Parse(next); } }
    public long nextlong { get { return long.Parse(next); } }
    public double nextdouble { get { return double.Parse(next); } }
}