Official

G - One More Grid Task Editorial by en_translator


Preface: solving this problem in a time complexity of about \(300^3 \times \log_2(300) \approx 2.2 \times 10^8\) requires a descent caution on the constant factor, if not impossible. Instead, this editorial will strive to solving it in \(300^3\) time, which is actually possible.

Note the distinctive constraints of \(1 \le A_i \le 300\).

Recall that \(f(R) = \) (the sum of integers written on the squares in \(R\)) \(\times\) (the minimum integer written on a square in \(R\)).
Let us dare to fix the minimum integer \(m\) written on a square in \(R\), which appears as the second term. There are \(300\) possible values.

Moreover, let us fix the bottommost column of a rectangular region. We can try \(N\) possible candidates.

Now consider the following value:

  • \(H_{i,j} = \) (when the \(i\)-th column is the bottommost one, how further can the \(j\)-th row can be extended upward, subject to the minimum value \(m\)?)

Consider inserting columns (\(M\) times) in ascending order of \(H_{i,j}\).

When a column is added, note the maximal contiguous already-added columns containing the one added now. These rows can be extended \(H_{i,j}\) rows upward (where the bottleneck is the \(j\)-th column), but no more.
Then, the sum of integers in the maximal rectangular region can be obtained in an \(O(1)\) time as a two-dimensional cumulative sum, and the minimum integer in in the region is at least \(m\).
Thus, we can exhaustively inspect the maximal regions whose minimum value is at least \(m\).

We can avoid an excessive \(\log\) by managing the maximal already-added consecutive rows in manner of a connected list, and sorting in ascending order of \(H_{i,j}\) based on the fact that \(H_{i,j} = H_{i-1,j}+1\) or \(H_{i,j}=0\) holds. For more details, see also the sample code.

Hence, the problem can be solved in a total of \(O(NM \max A_i)\) time.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int sum2d(int fx,int fy,int tx,int ty,vector<vector<int>> &s){
  if(fx>tx || fy>ty){return 0;}
  if(fx==0 && fy==0){return s[tx][ty];}
  else if(fx==0){
    return s[tx][ty]-s[tx][fy-1];
  }
  else if(fy==0){
    return s[tx][ty]-s[fx-1][ty];
  }
  else{
    return s[tx][ty]-s[tx][fy-1]-s[fx-1][ty]+s[fx-1][fy-1];
  }
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n,m;
  cin >> n >> m;
  vector<vector<int>> a(n,vector<int>(m));
  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      cin >> a[i][j];
    }
  }
  vector<vector<int>> s=a;
  for(int i=1;i<n;i++){
    for(int j=0;j<m;j++){s[i][j]+=s[i-1][j];}
  }
  for(int i=0;i<n;i++){
    for(int j=1;j<m;j++){s[i][j]+=s[i][j-1];}
  }

  long long res=0;
  for(int mi=1;mi<=300;mi++){
    vector<pair<int,int>> vp(m);
    for(int i=0;i<m;i++){
      vp[i].first=0;
      vp[i].second=i;
    }

    for(int i=0;i<n;i++){
      vector<pair<int,int>> top,bot;
      for(auto &nx : vp){
        if(a[i][nx.second]>=mi){
          top.push_back({nx.first+1,nx.second});
        }
        else{
          bot.push_back({0,nx.second});
        }
      }
      vp.clear();
      for(auto &nx : top){vp.push_back(nx);}
      for(auto &nx : bot){vp.push_back(nx);}

      vector<int> lef(m),rig(m);
      for(int j=0;j<m;j++){
        lef[j]=j-1;
        rig[j]=j+1;
      }

      for(auto &nx : vp){
        int cl=lef[nx.second];
        int cr=rig[nx.second];
        if(cl>=0){rig[cl]=cr;}
        if(cr<m){lef[cr]=cl;}
        long long cf=sum2d(i-nx.first+1,cl+1,i,cr-1,s);
        cf*=mi;
        res=max(res,cf);
      }
    }
  }
  cout << res << "\n";
  return 0;
}

posted:
last update: