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
c
1,1
c
1,2
...
c
1,W
c
2,1
c
2,2
...
c
2,W
:
c
H,1
c
H,2
...
c
H,W
In the first line, two integers
H
and
W
separated by a space character are given. In the following
H
lines,
c
i
,
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

Submitted solutions:

code_snippet: #include <cstdio>
#include <stack>
using namespace std;
const int maxv=1401;
int C[maxv][maxv];
int D[maxv][maxv];
int H,W;
int maxsquare(){
    int largest=0;
    for(int i=0;i<H;i++){
        stack<pair<int,int>> rect;
        for(int j=0;j<=W;j++){
            if(rect.empty()){
                rect.push(make_pair(j,D[i][j]));
            }else if(D[i][j]>rect.top().second){
                rect.push(make_pair(j,D[i][j]));
            }else if(D[i][j]<rect.top().second){
                int c;
                while(!rect.empty()&&D[i][j]<rect.top().second){
                    c=rect.top().first;
                    int d=rect.top().second;
                    int m=(j-c)*d;
                    largest=max(largest,m);
                    rect.pop();
                }
                rect.push(make_pair(c,D[i][j]));
            }
        }
    }
    return largest;
}
int main(){
    scanf("%d %d",&H,&W);
    for(int i=0;i<H;i++){
        for(int j=0;j<W;j++){
            scanf("%d",&C[i][j]);
        }
    }
    for(int i=0;i<W;i++){
        for(int j=0;j<H;j++){
            if(C[j][i]){
                D[j][i]=0;
            }else{
                if(j!=0){
                    D[j][i]=1+D[j-1][i];
                }else D[j][i]=1;    
            }
        }
    }
    for(int i=0;i<H;i++){
        D[i][W]=0;
    }
    int u=maxsquare();
    printf("%d\n",u);
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 18316
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
#include <chrono>
#include <complex>
#include <cmath>
#include <unistd.h>
#define pc_u putchar
#pragma GCC target ("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i,a,b) for(it i=(it)(a);i<(it)b;i++)
#define rep2(i,a,b,c) for(it i=(it)(a);i<(it)b;i+=(it)c)
#define repp(i,a,b) for(it i=(it)(a);i<=(it)b;i++)
#define repp2(i,a,b,c) for(it i=(it)(a);i<=(it)b;i+=(it)c)
#define irep(i,a,b) for(int i=(int)(a);i<(int)b;i++)
#define irep2(i,a,b,c) for(int i=(int)(a);i<(int)b;i+=c)
#define irepp(i,a,b) for(int i=(int)(a);i<=(int)b;i++)
#define irepp2(i,a,b,c) for(int i=(int)(a);i<=(int)b;i+=c)
#define nrep(i,a,b) for(it i=(it)(a)-1;i>=(it)b;i--)
#define nrepp(i,a,b) for(it i=(it)(a);i>=(it)b;i--)
#define inrep(i,a,b) for(int i=(int)(a)-1;i>=(int)b;i--)
#define inrepp(i,a,b) for(int i=(int)(a);i>=(int)b;i--)
#define inrep2(i,a,b,c) for(int i=(int)(a)-1;i>=(int)b;i-=c)
#define inrepp2(i,a,b,c) for(int i=(int)(a);i>=(int)b;i-=c)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define Min(x) *min_element(all(x))
#define Max(x) *max_element(all(x))
#define popcount(x) __builtin_popcountll(x)
#define moda 998244353LL
#define modb 1000000007LL
#define modc 968244353LL
#define dai 2502502502502502502LL
#define sho -dai
#define aoi 1e18+1e6
#define giri 1010000000
#define en 3.14159265358979
#define eps 1e-14
#define fi first
#define se second
#define elif else if
template<typename T> using pq=priority_queue<T>;
template<typename T> using pqg=priority_queue<T,vector<T>,greater<T>>;
#define uni(a) a.erase(unique(all(a)),a.end())
using it=long long;
using itn=int;
using un=unsigned long long;
using idb=double;
using db=long double;
using st=string;
using ch=char;
using bo=bool;
using P=pair<it,it>;
using ip=pair<int,int>;
using vi=vector<it>;
using ivi=vector<int>;
using ivd=vector<idb>;
using vd=vector<db>;
using vs=vector<st>;
using vc=vector<ch>;
using vb=vector<bo>;
using vp=vector<P>;
using ivp=vector<ip>;
using sp=set<P>;
using isp=set<ip>;
using ss=set<st>;
using sca=set<ch>;
using si=set<it>;
using isi=set<int>;
using svi=set<vi>;
using svb=set<vb>;
using vvi=vector<vi>;
using ivvi=vector<ivi>;
using ivvd=vector<ivd>;
using vvd=vector<vd>;
using vvs=vector<vs>;
using vvb=vector<vb>;
using vvc=vector<vc>;
using vvp=vector<vp>;
using ivvp=vector<ivp>;
using vsi=vector<si>;
using ivsi=vector<isi>;
using isvi=set<ivi>;
using vsc=vector<sca>;
using vsp=vector<sp>;
using ivsp=vector<isp>;
using vvsi=vector<vsi>;
using ivvsi=vector<ivsi>;
using vvsp=vector<vsp>;
using ivvsp=vector<ivsp>;
using svvb=set<vvb>;
using vvvi=vector<vvi>;
using ivvvi=vector<ivvi>;
using ivvvd=vector<ivvd>;
using vvvd=vector<vvd>;
using vvvb=vector<vvb>;
using ivvvp=vector<ivvp>;
using vvvp=vector<vvp>;
using vvvvi=vector<vvvi>;
using ivvvvi=vector<ivvvi>;
using vvvvd=vector<vvvd>;
using vvvvb=vector<vvvb>;
using ivvvvp=vector<ivvvp>;
using vvvvp=vector<vvvp>;
using ivvvvvi=vector<ivvvvi>;
using vvvvvi=vector<vvvvi>;
using ivvvvvvi=vector<ivvvvvi>;
using vvvvvvi=vector<vvvvvi>;
using ivvvvvvvi=vector<ivvvvvvi>;
using vvvvvvvi=vector<vvvvvvi>;
using vvvvvvvvi=vector<vvvvvvvi>;
const int dx[8]={0,1,0,-1,1,1,-1,-1};
const int dy[8]={1,0,-1,0,1,-1,1,-1};
st abc="abcdefghijklmnopqrstuvwxyz";
st ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
st num="0123456789";
st mb="xo";
st MB="XO";
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template<class T> using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

namespace {

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  int s = (int)v.size();
  for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
  return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}

istream &operator>>(istream &is, __int128_t &x) {
  string S;
  is >> S;
  x = 0;
  int flag = 0;
  for (auto &c : S) {
    if (c == '-') {
      flag = true;
      continue;
    }
    x *= 10;
    x += c - '0';
  }
  if (flag) x = -x;
  return is;
}

istream &operator>>(istream &is, __uint128_t &x) {
  string S;
  is >> S;
  x = 0;
  for (auto &c : S) {
    x *= 10;
    x += c - '0';
  }
  return is;
}

ostream &operator<<(ostream &os, __int128_t x) {
  if (x == 0) return os << 0;
  if (x < 0) os << '-', x = -x;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}
ostream &operator<<(ostream &os, __uint128_t x) {
  if (x == 0) return os << 0;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}

void input() {}
template <typename T, class... U>
void input(T &t, U &...u) {
  cin >> t;
  input(u...);
}
template <typename T, class... U>
void input1(T &t, U &...u) {
  input(u...);
}
void print() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void print(const T &t, const U &...u) {
  cout << t;
  if (sizeof...(u)) cout << sep;
  print(u...);
}
template <typename T, class... U, char sep = ' '>
void print1(const T &t, const U &...u) {
  print(u...);
}

struct IoSetupNya {
  IoSetupNya() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(7);
  }
} iosetupnya;

}  //namespace Nyaan

template<typename T>
T Sum(vector<T> &a){
  T s=0;
  for(auto i:a)s+=i;
  return s;
}

template<typename T>
T Sum(vector<T> &a,int l,int r){
  T s=0;
  irep(i,l,r)s+=a[i];
  return s;
}

template <typename T>
void dec(vector<T> &t,T k=1){
  for(auto &i:t)i-=k;
}

template <typename T>
void inc(vector<T> &t,T k=1){
  for(auto &i:t)i+=k;
}

template <typename T>
vector<T> make_vec(int n,T t){
  vector<T> g(n);
  for(auto &i:g)i=t;
  return g;
}

template <typename T>
vector<T> subvec(vector<T> a,int f,int l){
  vector<T> g(l);
  irep(i,f,f+l)g[i-f]=a[i];
  return g;
}

template<typename T>
T gcda(T a,T b){
  if(!a||!b)return max(a,b);
  while(a%b&&b%a){
    if(a>b)a%=b;
    else b%=a;
  }
  return min(a,b);
}

it lcma(it a,it b){
  return a/gcda(a,b)*b;
}

db distance(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}

db getAngle(db xa, db ya, db xb, db yb, db xc, db yc) {
  //角BACを求める
  //E8さんの記事コピペ
  db VectorAB = sqrt((xb - xa) * (xb - xa) + (yb - ya) * (yb - ya));
  db VectorAC = sqrt((xc - xa) * (xc - xa) + (yc - ya) * (yc - ya));
  db Naiseki = (xb - xa) * (xc - xa) + (yb - ya) * (yc - ya);
  db cosTheta = Naiseki / (VectorAB * VectorAC);
  return acos(cosTheta) * 180.0 / 3.14159265358979;
}

long double segment_origin_dist(long double A, long double B, long double C, long double D) {
    // P = (A,B), Q = (C,D)
    long double vx = C - A, vy = D - B; // ベクトルPQ
    long double wx = -A, wy = -B;       // ベクトルPO (O-P)

    long double vv = vx * vx + vy * vy; // |PQ|^2
    if (vv == 0) {
        // P == Q の場合、点と原点の距離
        return sqrt(A * A + B * B);
    }

    long double t = (wx * vx + wy * vy) / vv; // 射影パラメータ

    long double nx, ny; // 最近点
    if (t <= 0) {
        nx = A; ny = B;
    } else if (t >= 1) {
        nx = C; ny = D;
    } else {
        nx = A + t * vx;
        ny = B + t * vy;
    }

    return sqrt(nx * nx + ny * ny);
}

bo outc(int h,int w,int x,int y){
  return (x<0||x>=h||y<0||y>=w);
}

template<typename T>
vector<vector<T>> nep(vector<T> a){
  vector<vector<T>> e;
  sort(all(a));
  do{
    e.emplace_back(a);
  }while(next_permutation(all(a)));
  return e;
}

template<typename T>
void chmin(T &a,T b){a=min(a,b);}
template<typename T>
void chmax(T &a,T b){a=max(a,b);}

void yn(bo a){print(a?string("Yes"):string("No"));}
void YN(bo a){print(a?string("YES"):string("NO"));}

struct dsu1{
  ivi par,siz;
  dsu1(int n){
    init(n);
  }
  void init(int n){
    irep(i,0,n){
      par.emplace_back(i);
    }
    siz.resize(n,1);
  }
  int leader(int u){
    if(par[u]==u)return u;
    return par[u]=leader(par[u]);
  }
  void merge(int u,int v){
    int ru=leader(u),rv=leader(v);
    if(ru==rv)return;
    if(size(ru)<size(rv))swap(ru,rv);
    siz[ru]+=siz[rv];
    par[rv]=ru;
  }
  bool same(int u,int v){
    return leader(u)==leader(v);
  }
  int size(int u){
    return siz[leader(u)];
  }
};

struct edge{
  int f;
  int t;
  it l;
};
void input(edge &a){input(a.f,a.t,a.l);}
bo comppppp(edge &a,edge &b){return a.l<b.l;}

it minspantree(vector<edge> &e,int n){
  /*
  与えられた辺を持つグラフの最小全域木を求める
  存在する場合はその答えを　存在しないならinf
  計算量はO(MlogM+N)くらい
  */
  vector<edge> g=e;sort(all(g),comppppp);
  it ans=0;
  dsu1 uf(n);
  for(auto i:g){
    if(!uf.same(i.f,i.t)){
      uf.merge(i.f,i.t);
      ans+=i.l;
    }
  }
  if(uf.size(0)==n)return ans;
  return dai;
}

/*#include <atcoder/all>
using namespace atcoder;
using mints=modint998244353;
using mint=modint;
using minto=modint1000000007;
using vm=vector<mint>;
using vms=vector<mints>;
using vmo=vector<minto>;
using vvm=vector<vm>;
using vvms=vector<vms>;
using vvmo=vector<vmo>;
using vvvm=vector<vvm>;
using vvvms=vector<vvms>;
using vvvmo=vector<vvmo>;
using vvvvm=vector<vvvm>;
using vvvvms=vector<vvvms>;
using vvvvmo=vector<vvvmo>;
using vvvvvm=vector<vvvvm>;
using vvvvvms=vector<vvvvms>;
using vvvvvmo=vector<vvvvmo>;
using vvvvvvm=vector<vvvvvm>;
using vvvvvvms=vector<vvvvvms>;
using vvvvvvmo=vector<vvvvvmo>;
using vvvvvvvms=vector<vvvvvvms>;
using vvvvvvvmo=vector<vvvvvvmo>;*/

/*総和をもとめるセグ木
struct nod{
  it val;
  nod(it v=0):val(v){}
};

nod op(nod a,nod b){return nod(a.val+b.val);}
nod e(){return nod(0);}

struct act{
  it a;
  act(it e=0):a(e){}
};

nod mapping(act f,nod x){return nod(f.a+x.val);}
act comp(act f,act g){return act(f.a+g.a);}
act id(){return act(0);}*/
//#define endl '\n'
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

void solve(){
  int h,w;input(h,w);
  ivvi a(h,ivi(w));input(a);
  ivi u(h,-1);int ans=0;
  irep(j,0,w){
    irep(i,0,h)
      if(u[i]<j){
        u[i]=j;
        while(u[i]<w&&!a[i][u[i]])u[i]++;
      }
    //print(j,u);
    ivvi c(w+1);
    irep(i,0,h)c[u[i]-j].emplace_back(i);
    dsu1 uf(h);vb s(h);
    inrep(p,w+1,0)
      for(int i:c[p]){
        if(i&&s[i-1])uf.merge(i-1,i);
        if(i!=h-1&&s[i+1])uf.merge(i+1,i);
        chmax(ans,p*uf.size(i));
        s[i]=1;
      }
  }
  print(ans);
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int t=1;//input(t);
  while(t--)solve();
}
accuracy: 1
time_ms: 90
memory_kb: 11172
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
template<typename T, typename F>
class CartesianTree {
  private:
    int N;
    F op;
    vector<int> left, right;
    vector<T> A;
  public:
    int root;
    vector<vector<int>> E;//2分木を構築
    vector<int> par;
    CartesianTree() {}
    CartesianTree(F _op, const vector<T> _A) 
    : A(_A), op(_op), N(_A.size()), left(_A.size()), right(_A.size()), E(_A.size()) {
      vector<int> st;
      par.resize(N, -1);
      for (int i = 0; i < N; i++) {
        int pre = -1;
        while (!st.empty() && op(A[st.back()], A[i])) {
          pre = st.back();
          st.pop_back();
        }
        if (pre != -1) {
          par[pre] = i;
        }
        if (!st.empty()) {
          par[i] = st.back();
        } else {
          root = i;
        }
        st.push_back(i);
      }
      for (int i = 0; i < N; i++) {
        if (par[i] != -1) {
          E[par[i]].push_back(i);
        }
      }
      calc();
    }  
    void calc() {
      for (int i = 0; i < N; i++) {
        left[i] = i;
        right[i] = i + 1;
      }
      auto dfs = [&] (auto &&self, int v) -> void {
        for (int w : E[v]) {
          self(self, w);
          left[v] = min(left[v], left[w]);
          right[v] = max(right[v], right[w]);
        }
      };
      dfs(dfs, root);
    }
    //A[v]が最大値または最小値(opによる)を取る区間を[l ,r)で返す
    pair<int, int> get_range(int v) {
      return make_pair(left[v], right[v]);
    }
};
bool op(int a, int b) {
  return a > b;
}
int main() {
  int H, W;
  cin >> H >> W;
  vector c(H, vector<int>(W));
  vector<int> h(W);
  int ans = 0;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      cin >> c[i][j];
      if (c[i][j] == 1) {
        h[j] = 0;
      } else {
        h[j]++;
      }
    }
    CartesianTree CT(op, h);
    CT.calc();
    for (int i = 0; i < W; i++) {
      auto [l, r] = CT.get_range(i);
      int width = 
      ans = max(ans, (r - l) * h[i]);
    }
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 240
memory_kb: 11264
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct rect
{
    int h, i;
    rect(int h, int i) : h(h), i(i) {}
};

int main()
{
    int h, w;
    cin >> h >> w;
    int grid[h][w];
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            cin >> grid[i][j];
        }
    }

    int dp[h][w];

    for (int j = 0; j < w; j++)
        dp[0][j] = grid[0][j] == 1 ? 0 : 1;

    for (int i = 1; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            dp[i][j] = grid[i][j] == 1 ? 0 : dp[i-1][j] + 1;
        }
    }

    int ans = 0;

    for (int i = 0; i < h; i++)
    {
        stack<rect> s;
        for (int j = 0; j < w; j++)
        {
            if (s.empty() || s.top().h < dp[i][j])
            {
                s.push( rect(dp[i][j], j) );
            }
            else if (s.top().h > dp[i][j])
            {
                int lasti = 0;
                while (!s.empty() && s.top().h > dp[i][j])
                {
                    ans = max( ans, s.top().h * (j - s.top().i) );
                    lasti = s.top().i;
                    s.pop();
                }
                s.push( rect(dp[i][j], lasti) );
            }
        }

        while (!s.empty())
        {
            ans = max( ans, s.top().h * (w - s.top().i) );
            s.pop();
        }
    }

    cout << ans << endl;

    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 18628
final_rank: 14

code_snippet: #include <bits/stdc++.h>
#include <cmath>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
using ll = long long;
using P = pair<int, int>;
using Pll = pair<ll, ll>;
void chmin(int& a, int b) { a = min(a, b); }
void chminll(ll& a, ll b) { a = min(a, b); }
void chminD(double& a, double b) { a = min(a, b); }
void chmax(int& a, int b) { a = max(a, b); }
void chmaxll(ll& a, ll b) { a = max(a, b); }
void chmaxD(double& a, double b) { a = max(a, b); }
int ceil(int a, int b) { return (a+b-1)/b; };
ll ceil_ll(ll a, ll b) { return (a+b-1)/b; }; 
// define DEBUG

void printVector(vector<vector<int>> a) {
  for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < a[0].size(); j++) {
      cout << a[i][j] << " ";
    }
    cout << endl;
  }
}

int main() {
  int h, w;
  cin >> h >> w;
  vector c(h,vector<int>(w));
  rep(i,h)rep(j,w) cin >> c[i][j];
  vector upper(h,vector<int>(w));
  rep(i,h)rep(j,w) {
    if (c[i][j]) continue;
    upper[i][j] = 1;
    if (i) upper[i][j] += upper[i-1][j];
  } 
  int ans = 0;
  rep(i,h) {
    vector<P> stack;
    vector<int> l(w), r(w,w);
    stack.emplace_back(-1,-1);
    rep(j,w) {
      while (stack.size()) {
        auto [hi,pj] = stack.back();
        if (hi <= upper[i][j]) break;
        r[pj] = j;
        stack.pop_back();
      }
      l[j] = stack.back().second+1;
      stack.emplace_back(upper[i][j],j);
    }
    rep(j,w) chmax(ans,upper[i][j]*(r[j]-l[j]));
  }
  cout << ans << endl;
  return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 19072
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using  ll=long long;
using  pii=pair<int,int>;
#define rep(a,b,c) for(int a=b;a<c;a++)
#define rep1(a,b,c) for(int a=b;a>=c;a--)
#define vc vector
#define pbk push_back
#define ebk emplace_back
#define fst first
#define snd second
#define sz(a) (int)a.size()
#define out(a,b,c,d,e) cout << a << " " << b << " " << c << " " << d << " " << e << endl


signed main() {
	int h,w;cin >> h >> w;
	vc g(h+1,vc<int>(w,0));
	int c;
	rep(i,1,h+1)rep(j,0,w){
		cin >> c;
		if(c==0) g[i][j]=g[i-1][j]+1;
		else g[i][j]=0;
	}
	/*rep(i,h,h+1){
		rep(j,0,w){
			cout << g[i][j] << " ";
		}
		cout << endl;
	}*/

	int ans=0;
	rep(i,1,h+1){
		stack<pii> st;
		rep(j,0,w+1){
			int ch=0;
			if(j<w) ch=g[i][j];
			while(!st.empty() && st.top().fst>ch){
				auto [ph,it]=st.top();
				st.pop();
				int lft=-1;
				if(!st.empty()) lft=st.top().snd;

				int tmp=ph*(j-(lft+1));
				//out(i,ls,a[ls].fst,j,a[ls].snd);
				//cout << tmp << endl;
				ans=max(ans,tmp);
			}
			st.push({ch,j});

		}
		//cout << i << " " << ans << endl;
	}
	cout << ans << endl;

}
accuracy: 1
time_ms: 120
memory_kb: 11264
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define INF 1e18
ll r,c,n,cnt=-1;
int main(){
    
    ll h,w,ans=0,f,sub;cin>>h>>w;
    vector<vector<bool>> ma(h,vector<bool>(w,false));
    vector<ll> a(w+1,0);
    stack<ll> s;
    for(ll i=0;i<h;i++)for(ll j=0;j<w;j++){
        cin>>f;
        if(f)ma[i][j]=true;
    }
    for(ll i=0;i<h;i++){
        for(ll j=0;j<w;j++){
            if(ma[i][j]==false)a[j]++;
            else a[j]=0;
        }
        for(ll j=0;j<=w;j++){
            while(s.size()&&a[s.top()]>=a[j]){
                f=a[s.top()];s.pop();
                sub=(s.empty()?-1:s.top());
                ans=max(ans,f*(j-sub-1));
            }
            s.push(j);
        }
        while(s.size())s.pop();
    }
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 150
memory_kb: 3684
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
int c[1405][1405],dp[1405][1405],l[1405][1405],r[1405][1405];
stack<int>sl;
stack<int>sr;
int main(){
	int h,w;
	cin>>h>>w;
	int i,j;
	for(i=1;i<=h;i++){
		for(j=1;j<=w;j++){
			cin>>c[i][j];
		}
	}
	for(j=1;j<=w;j++){
		for(i=1;i<=h;i++){
			if(c[i][j]==1){
				dp[i][j]=0;
			}else{
				dp[i][j]=dp[i-1][j]+1;
			}
		}
	}
	for(i=1;i<=h;i++){
		for(j=1;j<=w;j++){
			while(!sl.empty()&&dp[i][sl.top()]>=dp[i][j]){
				sl.pop();
			}
			if(sl.empty()){
				l[i][j]=0;
			}else{
				l[i][j]=sl.top();
			}
			sl.push(j);
		}
		while(!sl.empty()){
			sl.pop();
		}
	}
	for(i=1;i<=h;i++){
		for(j=w;j>=1;j--){
			while(!sr.empty()&&dp[i][sr.top()]>=dp[i][j]){
				sr.pop();
			}
			if(sr.empty()){
				r[i][j]=w+1;
			}else{
				r[i][j]=sr.top();
			}
			sr.push(j);
		}
		while(!sr.empty()){
			sr.pop();
		}
	}
	int ans=0;
	for(i=1;i<=h;i++){
		for(j=1;j<=w;j++){
			ans=max(ans,dp[i][j]*(r[i][j]-l[i][j]-1));
		}
	}
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 150
memory_kb: 34196
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
typedef pair<int,int> PII;
int getans(int a[],int m){
	vector<PII>p;
	p.push_back({-1,0});
	int mx=0;
	for(int i=1;i<=m;i++){
		while(p.back().first>=a[i]){
			int num=p.back().first;
			p.pop_back();
			int d=i-p.back().second-1;
			//mx=max(mx,d*a[i]);
			mx=max(mx,d*num);
		}
		int d=i-p.back().second;
		mx=max(mx,d*a[i]);
		p.push_back({a[i],i});
 	}
 	while(p.size()>1){
 		int num=p.back().first;
 		p.pop_back();
 		int d=m-p.back().second;
 	 	mx=max(mx,d*num);
 	}
 	return mx;
}
void solve(){
    int n,m;cin>>n>>m;
    int c[n+1][m+1];
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>c[i][j];
    int a[m+1];
    for(int i=0;i<=m;i++) a[i]=0;
    int ans=0;
    for(int i=1;i<=n;i++){
     	for(int j=1;j<=m;j++){
     	 	if(c[i][j]) a[j]=0;
     	 	else a[j]++;
     	}
		ans=max(ans,getans(a,m));
    }
    cout<<ans<<endl;
}
signed main(){
 	ios::sync_with_stdio(false);
 	cin.tie(0),cout.tie(0);
 	int t=1;
 	//cin>>t;
 	while(t--){
 		solve();
 	}
 	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 18724
final_rank: 5

code_snippet: #include <cstdio>
#include <iostream>
#include <stack>
#include <algorithm>

constexpr int MAX = 1'400;

struct Rectangle {
    int height;
    int pos;
};

// ひとつの行について求解
int get_largest_rectangle(int size, int buffer[]) {
    std::stack<Rectangle> S;
    int maxv = 0;
    buffer[size] = 0;

    for (int i = 0; i <= size; ++i) {
        Rectangle rect;
        rect.height = buffer[i];
        rect.pos = i;
        if (S.empty()) {
            S.push(rect);
        } else {
            if (S.top().height < rect.height) {
                S.push(rect);
            } else if (S.top().height > rect.height) {
                int target = i;
                while (!S.empty() && S.top().height >= rect.height) {
                    Rectangle pre = S.top();
                    S.pop();
                    int area = pre.height * (i - pre.pos);
                    maxv = std::max(maxv, area);
                    target = pre.pos;
                }
                rect.pos = target;
                S.push(rect);
            }
        }
    }

    return maxv;
}

int H, W;
int buffer[MAX][MAX];
int T[MAX][MAX];

// 前処理+求解
int get_largest_rectangle() {
    // 前処理
    for (int j = 0; j < W; ++j) {
        for (int i = 0; i < H; ++i) {
            if (buffer[i][j]) {
                // 汚れたタイル
                T[i][j] = 0;
            } else {
                // きれいなタイル
                T[i][j] = (i > 0) ? T[i - 1][j] + 1 : 1;
            }
        }
    }

    // 求解
    int maxv = 0;
    for (int i = 0; i < H; ++i) {
        maxv = std::max(maxv, get_largest_rectangle(W, T[i]));
    }

    return maxv;
}

int main() {
    scanf("%d %d", &H, &W);
    for (int i = 0; i < H; ++i) {
        for (int j = 0; j < W; ++j) {
            scanf("%d", &buffer[i][j]);
        }
    }

    std::cout << get_largest_rectangle() << std::endl;

    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 18936
final_rank: 6

code_snippet: #include <iostream>
#include <string>
#include <map>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <limits.h>
using namespace std;

struct rect {
    int pos;
    int height;
};


int main() {
    int H, W;
    cin >> H >> W;

    vector<vector<int>> c(1410, vector<int>(1410, 0));
    vector<vector<int>> rectHeight(1410, vector<int>(1410, 0));

    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            cin >> c[i][j];
        }
    }


    // 動的計画法を用いて解く
    // まず、長方形の高さを格納するための配列作成を行う(これも動的計画法)
    // 長方形の高さを格納するための配列 : 二次元の配列で、上に向かってきれいなタイルをカウントしていき、長方形の高さをヒストグラムに格納していく

    // 長方形の高さを格納するための配列を用いて長方形の最大の面積を求める この時、スタックを活用する
    // H,Wのループでやるが、Wのループ毎にスタックを用意する
    // Hのループの中にWのループがあり、Hのループが回る度にWのループで長方形の最大値が求まり。最終的にHのループが終わるころには、全体での長方形の最大面積が求まっているイメージ
    // 各Wループの処理は以下のイメージ
    // 0<=  i <Wでループ(※1)
    // 以下の条件でスタックへの追加・取り出しを行いつつ処理を行う
    // スタックに何もないとき→(i,recHeight(i,j))を格納 ※j : H方向のループカウンタ
    // スタックにあるとき
    //    - スタックのトップのrecHeightが、追加しようとしている情報のrecHeightよりも小さいとき : そのままスタックに追加
    //    - スタックのトップのrecHeightが、追加しようとしている情報のrecHeightと同じとき : 何もしない
    //    - スタックのトップのrecHeightが、追加しようとしている情報のrecHeightよりも大きいとき : 長方形が出来上がるため、以下の処理を実行したうえでスタックに追加
    //       スタックのトップを取り出し、長方形の面積を求める→現在のインデックスiと、スタックから取り出したインデックスiと、recHeightを用いれば長方形の面積が求まる (長方形の最大値も適宜記録しておく)
    //    ※スタックの中に情報が残っていて、長方形の面積の求め漏れが起きるのを防ぐために、rectHeightの、x座標がWの箇所には、0を格納しておき、※1のループも、 0<=  i <=Wで行う必要があるので注意

    // 長方形の高さを格納するための配列作成
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            // 汚いタイル
            if (c[i][j]) {
                rectHeight[i][j] = 0; // 高さは0
            }
            else { // きれいなタイル
                if (i == 0) {
                    rectHeight[i][j] = 1; // y座標が0できれいなタイルの場合、高さ1
                }
                else {
                    rectHeight[i][j] = rectHeight[i - 1][j] + 1; // 1つ前のy座標に格納されている高さ+1
                }
            }
        }
    }

    // 最大長方形を求める
    int maxRecArea = 0;
    for (int i = 0; i < H; i++) {
        stack<rect> s;
        for (int j = 0; j <= W; j++) {
            // j==Wの時はHeightに0を入れる
            if (j == W) {
                rectHeight[i][j] = 0;
            }

            rect tmpRect = { j, rectHeight[i][j] }; // 追加しようとしているrect

            // スタックに何もない
            if (s.empty()) {
                s.push(tmpRect);
            }
            // スタックにある
            else {

                //スタックのトップのrecHeightが、追加しようとしている情報のrecHeightよりも小さいとき
                if (s.top().height < tmpRect.height) {
                    s.push(tmpRect);
                }
                // スタックのトップのrecHeightが、追加しようとしている情報のrecHeightと同じときは何もしない
                // スタックのトップのrecHeightが、追加しようとしている情報のrecHeightよりも大きいとき
                if (s.top().height > tmpRect.height) {
                    // ひたすらにスタックから取り出す処理がない

                    // スタックが空でないかつ、スタックのトップのheightが、tmpRect.heightよりも大きいときはひたすらスタックから取り出し続ける
                    while (!s.empty() && s.top().height >= tmpRect.height) {
                        rect tmpTop = s.top();
                        s.pop(); // スタックのトップを取り出す

                        // 長方形の面積
                        int recArea = (j - tmpTop.pos) * tmpTop.height;
                        if (maxRecArea <= recArea) {
                            maxRecArea = recArea;
                        }

                        // スタックから取り出した後、新たにスタックに追加する場合は、rect構造体のposに注意
                        tmpRect.pos = tmpTop.pos;
                    }

                    // 長方形の面積算出後にスタックに追加
                    s.push(tmpRect);
                }
            }
        }
    }

    cout << maxRecArea << endl;
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 18692
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (i = 0; i < (int)(n); i++)
using ll = long long;

struct Rectangle
{
    int height;
    int pos;
};

int main()
{
    int h;
    int w;
    int i;
    int j;
    int c;
    int maxv;
    Rectangle cur;
    Rectangle prev;
    stack<Rectangle> S;
    int tgt;

    cin >> h >> w;
    vector<vector<int>> DP(h, vector<int>(w, 0));
    rep(i, h)
    {
        rep(j, w)
        {
            cin >> c;
            if (c == 0)
            {
                if (i == 0)
                {
                    DP.at(i).at(j) = 1;
                }
                else
                {
                    DP.at(i).at(j) = DP.at(i - 1).at(j) + 1;
                }
            }
        }
    }
    maxv = 0;
    rep(i, h)
    {
        rep(j, w)
        {
            cur.height = DP.at(i).at(j);
            cur.pos = j;
            if (S.empty())
            {
                S.push(cur);
            }
            else
            {
                if (S.top().height < cur.height)
                {
                    S.push(cur);
                }
                else
                {
                    tgt = j;
                    while (!S.empty() && S.top().height >= cur.height)
                    {
                        prev = S.top();
                        S.pop();
                        maxv = max(maxv, prev.height * (j - prev.pos));
                        tgt = prev.pos;
                    }
                    cur.pos = tgt;
                    S.push(cur);
                }
            }
        }
        tgt = w;
        while (!S.empty())
        {
            prev = S.top();
            S.pop();
            maxv = max(maxv, prev.height * (w - prev.pos));
        }
    }
    cout << maxv << endl;

    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 11008
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MAX = 1400;

int H, W;
int buffer[MAX][MAX];
int T[MAX][MAX];

struct Rectangle {
	int height, pos;
};

int getLargestRectangle(int size, int buffer[]) {
	stack<Rectangle> S;
	int maxv = 0;
	buffer[size] = 0;
	
	for (int i = 0; i <= size; ++i) {
		Rectangle rect;
		rect.height = buffer[i];
		rect.pos = i;
		if (S.empty()) {
			S.push(rect);
		} else if (S.top().height < rect.height) {
			S.push(rect);
		} else if (S.top().height > rect.height) {
			int target = i;
			while (!S.empty() && S.top().height >= rect.height) {
				Rectangle pre = S.top(); S.pop();
				int area = pre.height * (i - pre.pos);
				maxv = max(maxv, area);
				target = pre.pos;
			}
			rect.pos = target;
			S.push(rect);
		}
	}
	return maxv;
}

int getLargestRectangle() {
	for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j) {
			if (buffer[i][j]) {
				T[i][j] = 0;
			} else {
				T[i][j] = (i > 0) ? T[i-1][j] + 1 : 1;
			}
		}
	}
	
	int maxv = 0;
	for (int i = 0; i < H; ++i) {
		maxv = max(maxv, getLargestRectangle(W, T[i]));
	}
	
	return maxv;
}

int main() {
	cin >> H >> W;
	for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j) {
			cin >> buffer[i][j];
		}
	}
	
	cout << getLargestRectangle() << endl;
	
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 18692
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MAX = 1400;

int H, W;
int buffer[MAX][MAX];
int T[MAX][MAX];

struct Rectangle {
	int height, pos;
};

int getLargestRectangle(int size, int buffer[]) {
	stack<Rectangle> S;
	int maxv = 0;
	buffer[size] = 0;
	
	for (int i = 0; i <= size; ++i) {
		Rectangle rect;
		rect.height = buffer[i];
		rect.pos = i;
		if (S.empty()) {
			S.push(rect);
		} else if (S.top().height < rect.height) {
			S.push(rect);
		} else if (S.top().height > rect.height) {
			int target = i;
			while (!S.empty() && S.top().height >= rect.height) {
				Rectangle pre = S.top(); S.pop();
				int area = pre.height * (i - pre.pos);
				maxv = max(maxv, area);
				target = pre.pos;
			}
			rect.pos = target;
			S.push(rect);
		}
	}
	return maxv;
}

int getLargestRectangle() {
	for (int j = 0; j < W; ++j) {
		for (int i = 0; i < H; ++i) {
			if (buffer[i][j]) {
				T[i][j] = 0;
			} else {
				T[i][j] = (i > 0) ? T[i-1][j] + 1 : 1;
			}
		}
	}
	
	int maxv = 0;
	for (int i = 0; i < H; ++i) {
		maxv = max(maxv, getLargestRectangle(W, T[i]));
	}
	
	return maxv;
}

int main() {
	cin >> H >> W;
	for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j) {
			cin >> buffer[i][j];
		}
	}
	
	cout << getLargestRectangle() << endl;
	
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 18756
final_rank: 18

code_snippet: /******************************************************************************

                              Online C++ Compiler.
               Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.

*******************************************************************************/

#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <limits.h>

using namespace std;

int main()
{
    int h, w;
    cin >> h >> w;
    
    vector<vector<int> > mat(h, vector<int>(w)), heights(h, vector<int>(w));
    
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            cin >> mat[i][j];
        }
    }
    
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            if(mat[i][j] == 0) {
                if (i > 0) {
                    heights[i][j] = heights[i - 1][j] + 1;
                }
                else {
                    heights[i][j] = 1;
                }
            }
            else {
                heights[i][j] = 0;
            }
            // cout << heights[i][j] << " ";
        }
        // cout << endl;
    }
    
    int ans = 0;
    
    for (int i = 0; i < h; i++) {
        stack<pair<int, int> > st;
        
        for (int j = 0; j <= w; j++) {
            int curH = 0;
            if (j < w) {
                curH = heights[i][j];
            }
            
            while (!st.empty() && st.top().first >= curH) {
                auto [prevH, _] = st.top();
                st.pop();
                
                int left = -1;
                
                if (!st.empty()) {
                    left = st.top().second;
                }
                
                ans = max(ans, prevH * ((j - 1) - (left + 1) + 1));
            }
            
            st.push({curH, j});
        }
    }
    
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 18816
final_rank: 12

code_snippet: #include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef tuple<int, int, int> iii;
typedef pair<ll, ll> pll;
typedef vector<ii> vii;
typedef vector<ll> vll;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define LSOne(S) ((S) & -(S))

template <class T>
using ordered_set = tree<T, null_type, greater<T>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T>
bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template <class T>
bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }

using a2 = array<int, 2>;
void solve() {
    int n, m;
    cin >> n >> m;
    vector<vi> dp(n, vi(m));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int b;
            cin >> b;
            if (b == 1)
                dp[i][j] = 0;
            else
                dp[i][j] = (i ? dp[i - 1][j] : 0) + 1;
        }
    }

    auto largest_rect = [&](vi& A) {
        vector<a2> bounds(m);

        stack<a2> stk;
        stk.push({INT_MIN, -1});
        for (int i = 0; i < m; i++) {
            while (stk.top()[0] >= A[i]) stk.pop();
            bounds[i][0] = stk.top()[1];
            stk.push({A[i], i});
        }

        stk = stack<a2>();
        stk.push({INT_MIN, m});
        for (int i = m - 1; i >= 0; i--) {
            while (stk.top()[0] >= A[i]) stk.pop();
            bounds[i][1] = stk.top()[1];
            stk.push({A[i], i});
        }

        int ans = 0;
        for (int i = 0; i < m; i++) {
            auto [l, r] = bounds[i];
            ans = max(ans, (r - l - 1) * A[i]);
        }

        return ans;
    };

    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans = max(ans, largest_rect(dp[i]));
    }

    cout << ans << '\n';
}

int main() {
    ios_base::sync_with_stdio(0), cin.tie(0);

    int tc = 1;
    // cin >> tc;

    while (tc--) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 10744
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;

// const int M = 1e9 + 7;
const int M = 998244353;

ll bin(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b%2) ans = (a * ans)%M;
        a = (a*a)%M;
        b/=2;
    }
    return ans;
}

void solve(){
    int n, m; cin >> n >> m;
    vector<vector<int>> arr(n, vector<int>(m));
    vector<vector<int>> c(n, vector<int>(m));
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> arr[i][j];
            if(arr[i][j] == 1) c[i][j] = 0;
            else if(i == 0) c[i][j] = 1;
            else c[i][j] = c[i - 1][j] + 1;
        }
    }
    int ans = 0;
    for(int kk = 0; kk < n; kk++){
        vector<int> &arr = c[kk];
        stack<int> sl, sr;
        vector<int> right(m), left(m);
        for(int i = 0; i < m; i++){
            while(sl.size() && arr[i] <= arr[sl.top()]){
                sl.pop();
            }
            left[i] = (sl.empty() ? 0 : sl.top() + 1);
            sl.push(i);
        }
        for(int i = m - 1; i >= 0; i--){
            while(sr.size() && arr[i] <= arr[sr.top()]){
                sr.pop();
            }
            right[i] = (sr.empty() ? m - 1 : sr.top() - 1);
            sr.push(i);
        }
        for(int i = 0; i < m; i++){
            ans = max(ans, (right[i] - left[i] + 1) * arr[i]);
        }
    }
    cout << ans << '\n';
}

int32_t main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int _ = 1;
    // cin >> _;
    while(_--){
        solve();
    }
}
accuracy: 1
time_ms: 80
memory_kb: 18520
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;

void solve(){
    int n, m; cin >> n >> m;
    vector<vector<int>> arr(n, vector<int>(m));
    vector<vector<int>> c(n, vector<int>(m));
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> arr[i][j];
            if(arr[i][j] == 1) c[i][j] = 0;
            else if(i == 0) c[i][j] = 1;
            else c[i][j] = c[i - 1][j] + 1;
        }
    }
    int ans = 0;
    for(int kk = 0; kk < n; kk++){
        vector<int> &arr = c[kk];
        stack<int> sl, sr;
        vector<int> right(m), left(m);
        for(int i = 0; i < m; i++){
            while(sl.size() && arr[i] <= arr[sl.top()]){
                sl.pop();
            }
            left[i] = (sl.empty() ? 0 : sl.top() + 1);
            sl.push(i);
        }
        for(int i = m - 1; i >= 0; i--){
            while(sr.size() && arr[i] <= arr[sr.top()]){
                sr.pop();
            }
            right[i] = (sr.empty() ? m - 1 : sr.top() - 1);
            sr.push(i);
        }
        for(int i = 0; i < m; i++){
            ans = max(ans, (right[i] - left[i] + 1) * arr[i]);
        }
    }
    cout << ans << '\n';
}

int32_t main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int _ = 1;
    // cin >> _;
    while(_--){
        solve();
    }
}
accuracy: 1
time_ms: 80
memory_kb: 18492
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;

void solve(){
    int n, m; cin >> n >> m;
    vector<vector<int>> arr(n, vector<int>(m));
    vector<vector<int>> c(n, vector<int>(m));
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> arr[i][j];
            if(arr[i][j] == 1) c[i][j] = 0;
            else if(i == 0) c[i][j] = 1;
            else c[i][j] = c[i - 1][j] + 1;
        }
    }
    int ans = 0;
    for(int kk = 0; kk < n; kk++){
        vector<int> &arr = c[kk];
        stack<int> sl, sr;
        vector<int> right(m), left(m);
        for(int i = 0; i < m; i++){
            while(sl.size() && arr[i] <= arr[sl.top()]){
                sl.pop();
            }
            left[i] = (sl.empty() ? 0 : sl.top() + 1);
            sl.push(i);
        }
        for(int i = m - 1; i >= 0; i--){
            while(sr.size() && arr[i] <= arr[sr.top()]){
                sr.pop();
            }
            right[i] = (sr.empty() ? m - 1 : sr.top() - 1);
            sr.push(i);
        }
        for(int i = 0; i < m; i++){
            ans = max(ans, (right[i] - left[i] + 1) * arr[i]);
        }
    }
    cout << ans << '\n';
    return;
}

int32_t main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int _ = 1;
    // cin >> _;
    while(_--){
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 18816
final_rank: 3

code_snippet: #include <iostream>
#include <stdio.h>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <cmath>
#include <algorithm>
using namespace std;

int main () {
  int h, w;
  cin >> h >> w;

  int c[h][w];

  for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) cin >> c[i][j];

  int heights[h][w];

  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (c[i][j]) {
        heights[i][j] = 0;
      }
      else {
        if (i == 0) {
          heights[i][j] = 1;
        }
        else {
          heights[i][j] = heights[i - 1][j] + 1;
        }
      }
    }
  }

  int ans = 0;

  for (int i = 0; i < h; i++) {
    stack<pair<int, int> > st;
    for (int j = 0; j < w; j++) {
      int l = j;

      while (1) {
        if (st.empty()) {
          st.push(make_pair(heights[i][j], l));
          break;
        }
        else {
          pair<int, int> top = st.top();

          if (top.first < heights[i][j]) {
            st.push(make_pair(heights[i][j], l));
            break;
          }
          else if (top.first == heights[i][j]) {
            break;
          }
          else if (top.first > heights[i][j]) {
            ans = max(ans, top.first * (j - top.second));
          }

          l = top.second;
          st.pop();
        }
      }
    }

    while (!st.empty()) {
      pair<int, int> top = st.top();
      st.pop();
      ans = max(ans, top.first * (w - top.second));
    }
  }

  cout << ans << endl;
}
accuracy: 1
time_ms: 150
memory_kb: 18640
final_rank: 15