Problem:
Score : 500 points

Problem Statement

There are N towns on a plane. The i-th town is located at the coordinates (x_i,y_i). There may be more than one town at the same coordinates.

You can build a road between two towns at coordinates (a,b) and (c,d) for a cost of min(|a-c|,|b-d|) yen (the currency of Japan). It is not possible to build other types of roads.

Your objective is to build roads so that it will be possible to travel between every pair of towns by traversing roads. At least how much money is necessary to achieve this?

Constraints

2 ≤ N ≤ 10^5

0 ≤ x_i,y_i ≤ 10^9

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_N y_N

Output

Print the minimum necessary amount of money in order to build roads so that it will be possible to travel between every pair of towns by traversing roads.

Sample Input 1

3
1 5
3 9
7 8

Sample Output 1

3

Build a road between Towns 1 and 2, and another between Towns 2 and 3. The total cost is 2+1=3 yen.

Sample Input 2

6
8 3
4 9
12 19
18 1
13 5
7 6

Sample Output 2

8

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var N = sc.ReadInt();
        var XY1 = new Tuple<int, int, int>[N];
        for (int i = 0; i < N; i++)
        {
            var x = sc.ReadInt();
            var y = sc.ReadInt();
            XY1[i] = Tuple.Create(x, y, i);
        }
        XY1 = XY1.OrderBy(t => t.Item1).ToArray();
        var XY2 = XY1.OrderBy(t => t.Item2).ToArray();
        var edges = new List<Tuple<int, int, int>>();
        for (int i = 0; i < N; i++)
        {
            var x = XY1[i].Item1;
            var y = XY1[i].Item2;
            var no = XY1[i].Item3;
            if (i > 0)
            {
                edges.Add(Tuple.Create(no, XY1[i - 1].Item3, Math.Abs(x - XY1[i - 1].Item1)));
            }
            if (i < N - 1)
            {
                edges.Add(Tuple.Create(no, XY1[i + 1].Item3, Math.Abs(x - XY1[i + 1].Item1)));
            }
            
            Comparison<Tuple<int, int, int>> fy = (a, b) => a.Item2.CompareTo(b.Item2);
            var idy = Array.BinarySearch(XY2, Tuple.Create(0, y, 0), Comparer<Tuple<int, int, int>>.Create(fy));
            if (idy > 0)
            {
                edges.Add(Tuple.Create(no, XY2[idy - 1].Item3, Math.Abs(y - XY2[idy - 1].Item2)));
            }
            if (idy < N - 1)
            {
                edges.Add(Tuple.Create(no, XY2[idy + 1].Item3, Math.Abs(y - XY2[idy + 1].Item2)));
            }
        }
        var list = new List<Tuple<int, int, int>>();
        for (int i = 0; i < N; i++)
        {
            for (int j = i + 1; j < N; j++)
            {
                list.Add(Tuple.Create(i, j, Math.Min(Math.Abs(XY1[i].Item1 - XY1[j].Item1), Math.Abs(XY1[i].Item2 - XY1[j].Item2))));
            }
        }
        list = list.OrderBy(t => t.Item3).ToList();

        var uf = new UnionFind(N);
        var ans = 0L;
        edges = edges.OrderBy(e => e.Item3).ToList();
        foreach (var e in edges)
        {
            var a = e.Item1;
            var b = e.Item2;
            var c = e.Item3;
            if (!uf.Same(a, b))
            {
                uf.Union(a, b);
                ans += c;
            }
        }
        Console.WriteLine(ans);
    }

    class UnionFind
    {
        public int[] Parents { get; set; }
        public UnionFind(int n)
        {
            this.Parents = new int[n];
            for (int i = 0; i < n; i++)
            {
                this.Parents[i] = -1;
            }
        }
        public int Find(int x)
        {
            if (this.Parents[x] < 0) return x;
            this.Parents[x] = Find(this.Parents[x]);
            return this.Parents[x];
        }
        public int Size(int x)
        {
            return -this.Parents[this.Find(x)];
        }
        public bool Same(int x, int y)
        {
            return this.Find(x) == this.Find(y);
        }
        public bool Union(int x, int y)
        {
            x = this.Find(x);
            y = this.Find(y);
            if (x == y) return false;

            if (this.Size(x) < this.Size(y))
            {
                var tmp = x;
                x = y;
                y = tmp;
            }
            this.Parents[x] += this.Parents[y];
            this.Parents[y] = x;
            return true;
        }
        public int GetGroupCount()
        {
            return this.Parents.Count(p => p < 0);
        }
    }
    static Scanner sc = new Scanner();
}
static partial class Algorithm
{
    static int binarySearch<T>(IList<T> a, T v, IComparer<T> cmp, bool islb)
    {
        var l = 0;
        var r = a.Count - 1;
        while (l <= r)
        {
            var m = (l + r) / 2;
            var res = cmp.Compare(a[m], v);
            if (res < 0 || (res == 0 && !islb)) l = m + 1;
            else r = m - 1;
        }
        return l;
    }
    public static int LowerBound<T>(this IList<T> a, T v, Comparison<T> f) { return binarySearch(a, v, Comparer<T>.Create(f), true); }
    public static int LowerBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, true); }
    public static int UpperBound<T>(this IList<T> a, T v, Comparison<T> cmp) { return binarySearch(a, v, Comparer<T>.Create(cmp), false); }
    public static int UpperBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, false); }
}
class Scanner
{
    string[] S = new string[0];
    int Index = 0;
    char[] Separators = new char[] { ' ' };

    public string Next()
    {
        if (this.Index < this.S.Length) return this.S[this.Index++];
        var line = "";
        while (line == "") line = Console.ReadLine();
        this.S = line.Split(this.Separators, StringSplitOptions.RemoveEmptyEntries);
        if (this.S.Length == 0) return this.Next();
        this.Index = 0;
        return this.S[this.Index++];
    }
    public string ReadStr()
    {
        return this.Next();
    }
    public char ReadChar()
    {
        return this.Next()[0];
    }
    public int ReadInt()
    {
        return int.Parse(this.Next());
    }
    public uint ReadUInt()
    {
        return uint.Parse(this.Next());
    }
    public long ReadLong()
    {
        return long.Parse(this.Next());
    }
    public double ReadDouble()
    {
        return double.Parse(this.Next());
    }
    public Tuple<int, int> ReadTup(int add = 0)
    {
        return Tuple.Create(this.ReadInt() + add, this.ReadInt() + add);
    }
    public Tuple<long, long> ReadTupLong(int add = 0)
    {
        return Tuple.Create(this.ReadLong() + add, this.ReadLong() + add);
    }
    public Tuple<int, int, int> ReadTup3(int add = 0)
    {
        return Tuple.Create(this.ReadInt() + add, this.ReadInt() + add, this.ReadInt() + add);
    }
    public Tuple<int, int, int, int> ReadTup4(int add = 0)
    {
        return Tuple.Create(this.ReadInt() + add, this.ReadInt() + add, this.ReadInt() + add, this.ReadInt() + add);
    }
    public int[] ReadIntArray(int n)
    {
        var array = new int[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadInt();
        }
        return array;
    }
    public long[] ReadLongArray(int n)
    {
        var array = new long[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadLong();
        }
        return array;
    }
    public double[] ReadDoubleArray(int n)
    {
        var array = new double[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadDouble();
        }
        return array;
    }
    public char[] ReadCharArray(int n)
    {
        var array = new char[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadChar();
        }
        return array;
    }
    public string[] ReadStrArray(int n)
    {
        var array = new string[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadStr();
        }
        return array;
    }
    public Tuple<long, long>[] ReadTupLongArray(int n, int add = 0)
    {
        var array = new Tuple<long, long>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTupLong(add);
        }
        return array;
    }
    public Tuple<int, int>[] ReadTupArray(int n, int add = 0)
    {
        var array = new Tuple<int, int>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTup(add);
        }
        return array;
    }
    public Tuple<int, int, int>[] ReadTup3Array(int n, int add = 0)
    {
        var array = new Tuple<int, int, int>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTup3(add);
        }
        return array;
    }
    public Tuple<int, int, int, int>[] ReadTup4Array(int n, int add = 0)
    {
        var array = new Tuple<int, int, int, int>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTup4(add);
        }
        return array;
    }
}