Problem:
Largest Rectangle

Given a matrix (H × W) which contains only 1 and 0, find the area of the largest rectangle which only contains 0s.

Input

H W
c1,1 c1,2 ... c1,W
c2,1 c2,2 ... c2,W
:
cH,1 cH,2 ... cH,W

In the first line, two integers H and W separated by a space character are given. In the following H lines, ci,j, elements of the H × W matrix, are given.

Output

Print the area (the number of 0s) of the largest rectangle.

Constraints

1 ≤ H, W ≤ 1,400

Sample Input

4 5
0 0 1 0 0
1 0 0 0 0
0 0 0 1 0
0 0 0 1 0

Sample Output

6

Solution in C# (judge verdict: Accepted)

using System.Linq;
using static System.Math;
using System.Collections.Generic;
using System;

public class P
{
    public int p { get; set; }
    public int h { get; set; }
}

public class hello
{
    public static void Main()
    {
        string[] line = Console.ReadLine().Trim().Split(' ');
        var h = int.Parse(line[0]);
        var w = int.Parse(line[1]);
        var a = new bool[h, w];
        for (int i = 0; i < h; i++)
        {
            line = Console.ReadLine().Trim().Split(' ');
            for (int j = 0; j < w; j++)
                if (line[j] == "1") a[i, j] = true;
        }
        var b = new int[h, w];
        for (int i = 0; i < w; i++) b[0, i] = a[0, i] ? 0 : 1;
        if (h == 1)
        {
            var t = new int[w + 1];
            for (int i = 0; i < w; i++) t[i] = b[0, i];
            Console.WriteLine(getRect(t, w + 1));
            goto exit;
        }
        for (int i = 1; i < h; i++)
            for (int j = 0; j < w; j++) b[i, j] = a[i, j] ? 0 : b[i - 1, j] + 1;
        var ans = getAns(b, h, w);
        Console.WriteLine(ans);
        exit:;
    }
    static long getAns(int[,] b, int h, int w)
    {
        var ans = 0L;
        var a = new int[w + 1];
        for (int i = 0; i < h; i++)
        {
            for (int j = 0; j < w; j++) a[j] = b[i, j];
            ans = Max(ans, getRect(a, w + 1));
        }
        return ans;
    }
    static long getRect(int[] a, int n)
    {
        var ans = 0L; var lastp = 0;
        var st = new Stack<P>();
        for (int i = 0; i < n; i++)
        {
            if (st.Count() == 0) st.Push(new P { p = i, h = a[i] });
            else
            {
                var w = st.Peek();
                if (a[i] > w.h) st.Push(new P { p = i, h = a[i] });
                else if (a[i] < w.h)
                {
                    while (true)
                    {
                        ans = Max(ans, (long)(i - w.p) * w.h);
                        lastp = w.p;
                        st.Pop();
                        if (st.Count() == 0) break;
                        w = st.Peek();
                        if (a[i] <= w.h) continue;
                        else break;
                    }
                    st.Push(new P { p = lastp, h = a[i] });
                }
            }
        }
        return ans;
    }
}