Problem:
Score : 1200 points

Problem Statement

Snuke loves flags.

Snuke is placing N flags on a line.

The i-th flag can be placed at either coordinate x_i or coordinate y_i.

Snuke thinks that the flags look nicer when the smallest distance between two of them, d, is larger. Find the maximum possible value of d.

Constraints

2 ≤ N ≤ 10^{4}

1 ≤ x_i, y_i ≤ 10^{9}

x_i and y_i are integers.

Input

The input is given from Standard Input in the following format:

N
x_1 y_1
:
x_N y_N

Output

Print the answer.

Sample Input 1

3
1 3
2 5
1 9

Sample Output 1

4

The optimal solution is to place the first flag at coordinate 1, the second flag at coordinate 5 and the third flag at coordinate 9. The smallest distance between two of the flags is 4 in this case.

Sample Input 2

5
2 2
2 2
2 2
2 2
2 2

Sample Output 2

0

There can be more than one flag at the same position.

Sample Input 3

22
93 6440
78 6647
862 11
8306 9689
798 99
801 521
188 206
6079 971
4559 209
50 94
92 6270
5403 560
803 83
1855 99
42 504
75 484
629 11
92 122
3359 37
28 16
648 14
11 269

Sample Output 3

17

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

partial class Solver
{
    public void Run()
    {
        var N = ni();
        var X = new int[N];
        var Y = new int[N];
        for (int i = 0; i < N; i++)
        {
            X[i] = ni();
            Y[i] = ni();
        }
        int lower = 0, upper = 1000000000;
        int ans = -1;
        while (lower <= upper)
        {
            var mid = (lower + upper) / 2;

            // x: false, y: true
            var twosat = new TwoSat(N);

            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (Math.Abs(X[i] - X[j]) < mid) twosat.AddNandClause(i, false, j, false);
                    if (Math.Abs(Y[i] - X[j]) < mid) twosat.AddNandClause(i, true, j, false);
                    if (Math.Abs(X[i] - Y[j]) < mid) twosat.AddNandClause(i, false, j, true);
                    if (Math.Abs(Y[i] - Y[j]) < mid) twosat.AddNandClause(i, true, j, true);
                }
            }
            bool[] dummy;
            if (twosat.Solve(out dummy))
            {
                ans = mid;
                lower = mid + 1;
            }
            else
            {
                upper = mid - 1;
            }
        }
        cout.WriteLine(ans);
    }
}

public struct TwoSatVariable
{
    public int Index;
    public bool TrueOfFalse;
}

public class TwoSatImplication
{
    public TwoSatVariable Variable1;
    public TwoSatVariable Variable2;
}

public class TwoSat
{
    private readonly int N;
    private readonly List<TwoSatImplication> Implications = new List<TwoSatImplication>();

    public TwoSat(int n) { N = n; }

    /// <summary>
    /// P OR Q
    /// </summary>
    public void AddOrClause(int variable1, bool trueOrFalse1, int variable2, bool trueOrFalse2)
    {
        // P or Q === (~P => Q) and (~Q =>P)
        AddImplication(variable1, !trueOrFalse1, variable2, trueOrFalse2);
        AddImplication(variable2, !trueOrFalse2, variable1, trueOrFalse1);
    }

    /// <summary>
    /// ~(P AND Q) (=== ~P OR ~Q)
    /// </summary>
    public void AddNandClause(int variable1, bool trueOrFalse1, int variable2, bool trueOrFalse2)
    {
        AddOrClause(variable1, !trueOrFalse1, variable2, !trueOrFalse2);
    }

    /// <summary>
    /// P (=== P OR P)
    /// </summary>
    public void AddIsTrueClause(int variable1, bool trueOrFalse1)
    {
        AddOrClause(variable1, trueOrFalse1, variable1, trueOrFalse1);
    }

    /// <summary>
    /// (P XOR Q) (=== (P OR Q) AND (~P OR ~Q))
    /// </summary>
    public void AddXorClause(int variable1, bool trueOrFalse1, int variable2, bool trueOrFalse2)
    {
        AddOrClause(variable1, trueOrFalse1, variable2, trueOrFalse2);
        AddOrClause(variable1, !trueOrFalse1, variable2, !trueOrFalse2);
    }

    /// <summary>
    /// P -> Q
    /// </summary>
    public void AddImplication(int variable1, bool trueOrFalse1, int variable2, bool trueOrFalse2)
    {
        Implications.Add(new TwoSatImplication
        {
            Variable1 = new TwoSatVariable { Index = variable1, TrueOfFalse = trueOrFalse1 },
            Variable2 = new TwoSatVariable { Index = variable2, TrueOfFalse = trueOrFalse2 },
        });
    }

    private int ToIndex(TwoSatVariable v)
    {
        return v.TrueOfFalse ? v.Index : v.Index + N;
    }

    public bool Solve(out bool[] value)
    {
        value = null;
        var adj = Enumerable.Range(0, N * 2).Select(_ => new List<int>()).ToArray();
        foreach (var c in Implications)
        {
            adj[ToIndex(c.Variable1)].Add(ToIndex(c.Variable2));
        }
        var scc = new StronglyConnectedComponent(adj);
        var groupIndex = scc.GetGroupArray();

        for (int i = 0; i < N; i++) if (groupIndex[i] == groupIndex[i + N]) return false;
        value = new bool[N];
        for (int i = 0; i < N; i++) if (groupIndex[i] > groupIndex[i + N]) value[i] = true;
        return true;
    }
}

public class StronglyConnectedComponent
{
    readonly int n;
    readonly bool[] isVisited;
    private readonly List<int>[] adjacent;
    private readonly List<int>[] inverseAdjacent;
    private readonly Stack<int> stack = new Stack<int>();

    public StronglyConnectedComponent(List<int>[] adj)
    {
        this.adjacent = adj;
        this.n = adj.Length;
        this.isVisited = new bool[n];
        this.inverseAdjacent = new List<int>[n];
        for (int i = 0; i < n; i++) inverseAdjacent[i] = new List<int>();
        for (int i = 0; i < n; i++)
        {
            foreach (var x in adj[i])
            {
                inverseAdjacent[x].Add(i);
            }
        }
    }

    void Traverse(int k, List<int>[] adjacent, List<int> label)
    {
        if (isVisited[k]) return;
        var order = new List<int>();
        stack.Push(k);
        while (stack.Count > 0)
        {
            var top = stack.Pop();
            if (isVisited[top]) continue;
            isVisited[top] = true;
            order.Add(top);
            foreach (var x in adjacent[top]) stack.Push(x);
        }
        order.Reverse();
        label.AddRange(order);
    }

    public List<List<int>> Run()
    {
        var label = new List<int>();
        for (int i = 0; i < n; i++)
            Traverse(i, adjacent, label);
        label.Reverse();
        Array.Clear(isVisited, 0, isVisited.Length);
        var components = new List<List<int>>();
        foreach (var x in label)
        {
            if (!isVisited[x])
            {
                var group = new List<int>();
                Traverse(x, inverseAdjacent, group);
                components.Add(group);
            }
        }
        return components;
    }

    public int[] GetGroupArray()
    {
        var component = Run();
        var group = new int[n];
        for (int i = 0; i < component.Count; i++)
        {
            foreach (var x in component[i])
            {
                group[x] = i;
            }
        }
        return group; // group index is topological order
    }
}
// PREWRITEN CODE BEGINS FROM HERE
partial class Solver : Scanner
{
    public static void Main(string[] args)
    {
        new Solver(Console.In, Console.Out).Run();
    }

    private readonly TextReader cin;
    private readonly TextWriter cout;

    public Solver(TextReader reader, TextWriter writer)
        : base(reader)
    {
        this.cin = reader;
        this.cout = writer;
    }
    public Solver(string input, TextWriter writer)
        : this(new StringReader(input), writer)
    {
    }

    private int ni() { return NextInt(); }
    private int[] ni(int n) { return NextIntArray(n); }
    private long nl() { return NextLong(); }
    private long[] nl(int n) { return NextLongArray(n); }
    private double nd() { return NextDouble(); }
    private string ns() { return Next(); }
    private string[] ns(int n) { return NextArray(n); }
}

public class Scanner
{
    private TextReader Reader;
    private Queue<string> TokenQueue = new Queue<string>();
    private readonly CultureInfo ci = CultureInfo.InvariantCulture;

    public Scanner()
        : this(Console.In)
    {
    }

    public Scanner(TextReader reader)
    {
        this.Reader = reader;
    }

    public int NextInt() { return int.Parse(Next(), ci); }
    public long NextLong() { return long.Parse(Next(), ci); }
    public double NextDouble() { return double.Parse(Next(), ci); }
    public string[] NextArray(int size)
    {
        var array = new string[size];
        for (int i = 0; i < size; i++) array[i] = Next();
        return array;
    }
    public int[] NextIntArray(int size)
    {
        var array = new int[size];
        for (int i = 0; i < size; i++) array[i] = NextInt();
        return array;
    }

    public long[] NextLongArray(int size)
    {
        var array = new long[size];
        for (int i = 0; i < size; i++) array[i] = NextLong();
        return array;
    }

    public string Next()
    {
        if (TokenQueue.Count == 0)
        {
            if (!StockTokens()) throw new InvalidOperationException();
        }
        return TokenQueue.Dequeue();
    }

    public bool HasNext()
    {
        if (TokenQueue.Count > 0)
            return true;
        return StockTokens();
    }

    private bool StockTokens()
    {
        while (true)
        {
            var line = Reader.ReadLine();
            if (line == null) return false;
            var tokens = line.Trim().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            if (tokens.Length == 0) continue;
            foreach (var token in tokens)
                TokenQueue.Enqueue(token);
            return true;
        }
    }
}