Problem:
Score : 200 points

Problem Statement

Given are integers a,b,c and d.
If x and y are integers and a \leq x \leq b and c\leq y \leq d hold, what is the maximum possible value of x \times y?

Constraints

-10^9 \leq a \leq b \leq 10^9

-10^9 \leq c \leq d \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

a b c d

Output

Print the answer.

Sample Input 1

1 2 1 1

Sample Output 1

2

If x = 1 and y = 1 then x \times y = 1.
If x = 2 and y = 1 then x \times y = 2.
Therefore, the answer is 2.

Sample Input 2

3 5 -4 -2

Sample Output 2

-6

The answer can be negative.

Sample Input 3

-1000000000 0 -1000000000 0

Sample Output 3

1000000000000000000

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

namespace AtCoder
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;

    class Program
    {
        static void Main()
        {
            var input = Console.ReadLine().Split(' ').Select(x => decimal.Parse(x)).ToArray();
            var a = input[0];
            var b = input[1];
            var c = input[2];
            var d = input[3];

            var maxab = a <= b ? b : a;
            var maxcd = c <= d ? d : c;
            var ac = a * c;
            var ad = a * d;
            var bc = b * c;
            var bd = b * d;
            var ans = 0m;

            ans = ac >= ad ? ac : ad;
            ans = ans >= bc ? ans : bc;
            ans = ans >= bd ? ans : bd;
            Output(ans.ToString());
        }
        private static void Output(string str)
        {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);

            Console.WriteLine(str);

            Console.Out.Flush();
        }

    }

    static class Extentions
    {
        #region 拡張メソッド（string）

        public static string LeftB(this string stTarget, int iByteSize)
        {
            return MidB(stTarget, 1, iByteSize);
        }

        public static string MidB(this string stTarget, int iStart)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, iStart - 1, bBytes.Length - iStart + 1);
        }

        public static string MidB(this string stTarget, int iStart, int iByteSize)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, iStart - 1, iByteSize);
        }

        public static string RightB(this string stTarget, int iByteSize)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, bBytes.Length - iByteSize, iByteSize);
        }

        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }

        /// <summary>
        /// カルチャに依存した比較、または大文字と小文字を区別しない比較などの序数による比較を指定できる Contains。
        /// </summary>
        /// <param name="value">対象文字列</param>
        /// <param name="partialValue">部分文字列</param>
        /// <param name="comparison">カルチャ、大文字と小文字の区別、および並べ替え規則を指定する StringComparison</param>
        /// <returns>一致する場合に true を返します。</returns>
        public static bool Contains(this string value, string partialValue, StringComparison comparison = 0)
        {
            return value.IndexOf(partialValue, comparison) >= 0;
        }

        public static bool IsNumeric(this string value)
        {
            return decimal.TryParse(value, out decimal d);
        }
        public static int ToInt32(this String number, int retValue = 0)
        {
            if (!number.IsNumeric()) return retValue;
            return int.Parse(number);
        }

        #endregion
    }

}


#region Template

/*
    using System;
    using System.Collections.Generic;
    using System.Linq;

    // 整数の入力========================================
    string[] input = Console.ReadLine().Split(' ');
    int a = int.Parse(input[0]);
    int b = int.Parse(input[1]);
    int c = int.Parse(Console.ReadLine());
    
    //配列操作========================================
    var a = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();

    int[] a = new int[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = int.Parse(input2[i]);
    }
    
    Array.Sort(a);
    Array.Reverse(a);
    
    // 最小公倍数========================================
    public static decimal Lcm(decimal a, decimal b)
    {
        return a * b / Gcd(a, b);
    }

    // ユークリッドの互除法 ========================================
    public static decimal Gcd(decimal a, decimal b)
    {
        if (a < b)
        {
            // 引数を入替えて自分を呼び出す
            return Gcd(b, a);
        }
        while (b != 0)
        {
            var remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }

    // 全bit探索========================================
    
    // input桁のbit列で全探索を行う
    for (int x = 0; x < Math.Pow(2, input.Length); x++)
    {
        var array = new bool[input.Length];

        // 右からk桁目を取り出す
        for (int k = 0; k < input.Length; k++)
        {
            var y = (x >> k) & 1;
            array[k] = y==1;
        }
    }

    // DFS(深さ探索)========================================
    
    static void Main()
    {
        var input = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        var h = input[0];
        var w = input[1];
        var meiro = new char[w, h];
        var reached = new bool[w, h];
        var sh = 0;
        var sw = 0;
        var gh = 0;
        var gw = 0;
        for (int i = 0; i < h; i++)
        {
            var x = Console.ReadLine();
            for (int j = 0; j < w; j++)
            {
                meiro[j, i] = x[j];
                // スタートとゴール地点を退避
                if (x[j] == 's')
                {
                    sh = i;
                    sw = j;
                }
                if (x[j] == 'g')
                {
                    gh = i;
                    gw = j;
                }
            }
        }

        Search(sw, sh, meiro, reached);

        var ans = "No";
        if (reached[gw, gh] == true)
        {
            ans = "Yes";
        }
        Output(ans);
    }
    private static void Search(int x, int y, char[,] meiro, bool[,] reached)
    {
        // 壁や迷路の外なら脱出
        if (x < 0 || y < 0 || x > meiro.GetLength(0) - 1 || y > meiro.GetLength(1) - 1 || meiro[x, y] == '#') return;
        // 到達済みの場合も脱出
        if (reached[x, y] == true) return;
        // 到達記録
        reached[x, y] = true;

        Search(x + 1, y, meiro, reached);
        Search(x, y + 1, meiro, reached);
        Search(x - 1, y, meiro, reached);
        Search(x, y - 1, meiro, reached);
    }


    // BFS(幅探索)========================================
    static void Main()
    {
        var input = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        var r = input[0];
        var c = input[1];
        var meiro = new char[r, c];
        var passed = new bool[r, c];
        var start = Console.ReadLine().Split(' ').Select(x => int.Parse(x) -1).ToList();
        var goal = Console.ReadLine().Split(' ').Select(x => int.Parse(x) -1).ToArray();
        for (int i = 0; i < r; i++)
        {
            var x = Console.ReadLine();
            for (int j = 0; j < c; j++)
            {
                meiro[i, j] = x[j];
            }
        }

        var numMoves = new int[r, c];
        var que = new Queue<int[]>();
        start.Add(0); // 深さ
        que.Enqueue(start.ToArray());
        BFS(que, passed, numMoves, meiro);

        Output(numMoves[goal[0], goal[1]].ToString());
    }
    private static void BFS(Queue<int[]> que, bool[,] passed, int[,] numMoves, char[,] meiro)
    {
        while (que.Count() > 0)
        {
            var p = que.Dequeue();

            var x = p[0];
            var y = p[1];
            // 壁や迷路の外なら脱出
            if (x < 0 || y < 0 || x > meiro.GetLength(0) - 1 || y > meiro.GetLength(1) - 1 || meiro[x, y] == '#') continue;
            // 到達済みの場合も脱出
            if (passed[x, y] == true) continue;
            // 到達記録
            passed[x, y] = true;
            numMoves[x, y] = p[2];
            que.Enqueue(new int[3] { x - 1, y    , p[2] + 1 });
            que.Enqueue(new int[3] { x + 1, y    , p[2] + 1 });
            que.Enqueue(new int[3] { x,     y - 1, p[2] + 1 });
            que.Enqueue(new int[3] { x,     y + 1, p[2] + 1 });
        }
    }

    //二分探索==============================================

    
        static void Main()
        {
            var n = Console.ReadLine().ToInt32();
            var a = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();
            var b = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();
            var c = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();

            long ans = 0;
            for (int i = 0; i < a.Count(); i++)
            {
                var aIdx = LowerBound(a, b[i]) - 1;
                if (aIdx < 0) continue;

                var cIdx = UpperBound(c, b[i]);
                if (cIdx > n - 1) continue;

                //組み合わせ
                long combi = (long)(aIdx + 1) * (long)(n - cIdx);
                ans += combi;
            }
            Output(ans.ToString());

        }
        private static int LowerBound(long[] arr, long target)
        {
            var min = 0;
            var max = arr.Length - 1;

            while (max >= min)
            {
                int mid = min + (max - min) / 2;
                if (arr[mid] < target)
                {
                    min = mid + 1;
                }
                else
                {
                    max = mid - 1;
                }
            }
            //target以上となる最初のインデックスを出力
            return min;
        }
        private static int UpperBound(long[] arr, long target)
        {
            var min = 0;
            var max = arr.Length - 1;

            while (max >= min)
            {
                var mid = (min + max) / 2;
                if (arr[mid] <= target)
                {
                    min = mid + 1;
                }
                else
                {
                    max = mid - 1;
                }
            }
            //target以上となる最初のインデックスを出力
            return min;
        }


    //出力========================================
    Console.WriteLine("");


    var sb = new StringBuilder();
    for (int j = 0; j<n; j++)
    {
        sb.AppendLine(a[j].ToString());
    }
    var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
    Console.SetOut(sw);
    Console.WriteLine(sb.ToString());
    Console.Out.Flush();
*/
#endregion