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;
using System.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
	static void Main()
	{
		string[] input = Console.ReadLine().Split(' ');
		int h = int.Parse(input[0]);
		int w = int.Parse(input[1]);
    long[,] matrix = new long[h,w];//行列
      
    for(int i = 0; i < h; i++)//それぞれの行
    {
    	long[] nums = Array.ConvertAll(Console.ReadLine().Split(' '),long.Parse);
    	for(int j = 0; j < w; j++) matrix[i,j] = 1-nums[j];//行の全ての成分
    }

		Console.WriteLine(LargestRectangleArea(matrix));
	}

  static long LargestRectangleArea(long[,] uses)
  {//長方形上で1の書かれたマスだけを用いた長方形の最大面積をO(HW)で返す
    long answer = 0;
    int h = uses.GetLength(0);
    int w = uses.GetLength(1);
    long[] heights = new long[w];
    for(int i = 0; i < h; i++)
    {
      for(int j = 0; j < w; j++)
      {
        if(uses[i,j] == 1) heights[j]++;
        else heights[j] = 0;
      }
      //Console.WriteLine(LargestRectangle(heights)+"a");
      answer = Math.Max(answer,LargestRectangle(heights));
    }

    return answer;
  }

  static long LargestRectangle(long[] lengths)
  {//x軸に接する底辺1、高さlengthsの長方形を繋げた時、最大長方形の面積をO(n)で返す
    if(lengths.Length == 0) return 0;
    long answer = lengths[0];
    int n = lengths.Length;
    var rectangleStack = new Stack<long[]>();//x座標と高さ
    rectangleStack.Push(new long[2]{0,lengths[0]});
    long[] topMemo = new long[2];
    
    for(int i = 1; i < n; i++)
    {
      if(rectangleStack.Count() > 0) topMemo = rectangleStack.Peek();
      
      if(topMemo[1] < lengths[i]) rectangleStack.Push(new long[2]{i,lengths[i]});
      else if(topMemo[1] > lengths[i])
      {
        long memo = 0;
        while(rectangleStack.Count() > 0)
        {
          if(rectangleStack.Peek()[1] > lengths[i])
          {
            answer = Math.Max(answer, rectangleStack.Peek()[1]*(i-rectangleStack.Peek()[0]));
            memo = rectangleStack.Peek()[0];
            
            if(rectangleStack.Count() == 1)
            {
              rectangleStack.Pop();
              rectangleStack.Push(new long[2]{memo, lengths[i]});
              break;
            }
            else rectangleStack.Pop();
          }else
          {
            rectangleStack.Push(new long[2]{memo, lengths[i]});
            break;
          }
        }
      }

      if(i == n-1 && rectangleStack.Count() > 0)
      {
        while(rectangleStack.Count() > 0)
        {
          answer = Math.Max(answer, rectangleStack.Peek()[1]*(i-rectangleStack.Peek()[0]+1));
          rectangleStack.Pop();
        }
      }
    }

    return answer;
  }
  
}