Problem:
Score : 600 points

Problem Statement

There are N points in a two-dimensional plane. The initial coordinates of the i-th point are (x_i, y_i). Now, each point starts moving at a speed of 1 per second, in a direction parallel to the x- or y- axis. You are given a character d_i that represents the specific direction in which the i-th point moves, as follows:

If d_i = R, the i-th point moves in the positive x direction;

If d_i = L, the i-th point moves in the negative x direction;

If d_i = U, the i-th point moves in the positive y direction;

If d_i = D, the i-th point moves in the negative y direction.

You can stop all the points at some moment of your choice after they start moving (including the moment they start moving).
Then, let x_{max} and x_{min} be the maximum and minimum among the x-coordinates of the N points, respectively. Similarly, let y_{max} and y_{min} be the maximum and minimum among the y-coordinates of the N points, respectively.

Find the minimum possible value of (x_{max} - x_{min}) \times (y_{max} - y_{min}) and print it.

Constraints

1 \leq N \leq 10^5

-10^8 \leq x_i,\ y_i \leq 10^8

x_i and y_i are integers.

d_i is R, L, U, or D.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1 d_1
x_2 y_2 d_2
.
.
.
x_N y_N d_N

Output

Print the minimum possible value of (x_{max} - x_{min}) \times (y_{max} - y_{min}).

The output will be considered correct when its absolute or relative error from the judge's output is at most 10^{-9}.

Sample Input 1

2
0 3 D
3 0 L

Sample Output 1

0

After three seconds, the two points will meet at the origin. The value in question will be 0 at that moment.

Sample Input 2

5
-7 -10 U
7 -6 U
-8 7 D
-3 3 D
0 -6 R

Sample Output 2

97.5

The answer may not be an integer.

Sample Input 3

20
6 -10 R
-4 -9 U
9 6 D
-3 -2 R
0 7 D
4 5 D
10 -10 U
-1 -8 U
10 -6 D
8 -5 U
6 4 D
0 3 D
7 9 R
9 -4 R
3 10 D
1 9 U
1 -6 U
9 -8 R
6 7 D
7 -3 D

Sample Output 3

273

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

using CompLib.Util;
using System;

public class Program
{
    int N;
    const decimal Inf = 1000000000;
    decimal RYMin, RYMax, RXMin, RXMax;
    decimal LYMin, LYMax, LXMin, LXMax;
    decimal UYMin, UYMax, UXMin, UXMax;
    decimal DYMin, DYMax, DXMin, DXMax;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();

        RYMin = LYMin = UYMin = DYMin = Inf;
        RXMin = LXMin = UXMin = DXMin = Inf;
        RYMax = LYMax = UYMax = DYMax = -Inf;
        RXMax = LXMax = UXMax = DXMax = -Inf;

        for (int i = 0; i < N; i++)
        {
            long x = sc.NextLong();
            long y = sc.NextLong();

            char d = sc.NextChar();

            switch (d)
            {
                case 'U':
                    UXMax = Math.Max(UXMax, x);
                    UYMax = Math.Max(UYMax, y);
                    UXMin = Math.Min(UXMin, x);
                    UYMin = Math.Min(UYMin, y);
                    break;
                case 'D':
                    DXMax = Math.Max(DXMax, x);
                    DYMax = Math.Max(DYMax, y);
                    DXMin = Math.Min(DXMin, x);
                    DYMin = Math.Min(DYMin, y);
                    break;
                case 'L':
                    LXMax = Math.Max(LXMax, x);
                    LYMax = Math.Max(LYMax, y);
                    LXMin = Math.Min(LXMin, x);
                    LYMin = Math.Min(LYMin, y);
                    break;
                case 'R':
                    RXMax = Math.Max(RXMax, x);
                    RYMax = Math.Max(RYMax, y);
                    RXMin = Math.Min(RXMin, x);
                    RYMin = Math.Min(RYMin, y);
                    break;
            }
        }
        decimal ans = S(0);

        // X,Yの最大、最小が切り替わるタイミングが候補
        {
            // RXMinがx最小じゃなくなるタイミング
            decimal udXMin = Math.Min(UXMin, DXMin);
            {
                decimal ng = 0;
                decimal ok = Inf * 2;
                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok + ng) / 2;
                    if (RXMin + med < Math.Min(LXMin - med, udXMin))
                    {
                        ng = med;
                    }
                    else
                    {
                        ok = med;
                    }
                }
                ans = Math.Min(ans, S(ok));
            }
            // LMinがx最小になるタイミング
            {
                decimal ng2 = 0;
                decimal ok2 = Inf * 2;
                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok2 + ng2) / 2;
                    if (LXMin - med <= Math.Min(RXMin + med, udXMin))
                    {
                        ok2 = med;
                    }
                    else
                    {
                        ng2 = med;
                    }
                }
                ans = Math.Min(ans, S(ok2));
            }
        }
        {
            // LXMaxがx最大じゃなくなるタイミング
            decimal udXMax = Math.Min(UXMax, DXMax);
            {
                decimal ng = 0;
                decimal ok = Inf * 2;
                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok + ng) / 2;
                    if (LXMax - med > Math.Min(RXMax + med, udXMax))
                    {
                        ng = med;
                    }
                    else
                    {
                        ok = med;
                    }
                }
                ans = Math.Min(ans, S(ok));
            }
            // RMaxがx最大になるタイミング
            {
                decimal ng2 = 0;
                decimal ok2 = Inf * 2;
                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok2 + ng2) / 2;
                    if (RXMax + med >= Math.Min(LXMax - med, udXMax))
                    {
                        ok2 = med;
                    }
                    else
                    {
                        ng2 = med;
                    }
                }
                ans = Math.Min(ans, S(ok2));
            }
        }
        {
            decimal lrYMin = Math.Min(LYMin, RYMin);
            // Y最小
            // UYminが最小じゃなくなる
            {
                decimal ok = Inf * 2;
                decimal ng = 0;

                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok + ng) / 2;
                    if (UYMin + med < Math.Min(DYMin - med, lrYMin))
                    {
                        ng = med;
                    }
                    else
                    {
                        ok = med;
                    }
                }

                ans = Math.Min(ans, S(ok));
            }

            // DYminが最小になる
            {
                decimal ok2 = Inf * 2;
                decimal ng2 = 0;
                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok2 + ng2) / 2;
                    if (DYMin - med <= Math.Min(UYMin + med, lrYMin))
                    {
                        ok2 = med;
                    }
                    else
                    {
                        ng2 = med;
                    }
                }
                ans = Math.Min(ans, S(ok2));
            }
        }
        {
            // y最大
            decimal lrYMax = Math.Max(LYMax, RYMax);

            // DYMaxがy最大じゃなくなる
            {
                decimal ok = Inf * 2;
                decimal ng = 0;
                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok + ng) / 2;
                    if (DYMax - med < Math.Max(UYMax + med, lrYMax))
                    {
                        ok = med;
                    }
                    else
                    {
                        ng = med;
                    }
                }
                ans = Math.Min(ans, S(ok));
            }

            // UYMaxがy最大になる
            {
                decimal ok2 = Inf * 2;
                decimal ng2 = 0;

                for (int i = 0; i < 500; i++)
                {
                    decimal med = (ok2 + ng2) / 2;
                    if (UYMax + med >= Math.Max(DYMax - med, lrYMax))
                    {
                        ok2 = med;
                    }
                    else
                    {
                        ng2 = med;
                    }
                }
                ans = Math.Min(ans, S(ok2));
            }
        }
        Console.WriteLine("{0:f15}", ans);
    }

    decimal S(decimal time)
    {
        decimal xMax = Math.Max(RXMax + time, Math.Max(LXMax - time, Math.Max(UXMax, DXMax)));
        decimal xMin = Math.Min(RXMin + time, Math.Min(LXMin - time, Math.Min(UXMin, DXMin)));
        decimal yMax = Math.Max(RYMax, Math.Max(LYMax, Math.Max(UYMax + time, DYMax - time)));
        decimal yMin = Math.Min(RYMin, Math.Min(LYMin, Math.Min(UYMin + time, DYMin - time)));

        return (xMax - xMin) * (yMax - yMin);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Util
{
    using System;
    using System.Linq;
    class Scanner
    {
        private int _index;
        private string[] _line;
        const char separator = ' ';

        public Scanner()
        {
            _index = 0;
            _line = new string[0];
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(separator);
                _index = 0;
            }
            return _line[_index++];
        }
        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(separator);
            _index = _line.Length;
            return _line;
        }
        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
    }
}