#include <bits/stdc++.h>
#define ll long long
#define el cout << '\n'
#define ii pair<int, int>
#define fi first
#define se second
using namespace std;
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
if (fopen("TABLE3.INP", "r"))
{
freopen("TABLE3.INP", "r", stdin);
freopen("TABLE3.OUT", "w", stdout);
}
int n, m;
cin >> n >> m;
vector<vector<int>> a(n + 1, vector<int>(m + 1));
vector<int> vals;
vals.reserve(n * m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
{
cin >> a[i][j];
vals.push_back(a[i][j]);
}
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
auto get_id = [&](int x){
return lower_bound(vals.begin(), vals.end(), x) - vals.begin();
};
int V = (int)vals.size();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
a[i][j] = get_id(a[i][j]);
auto idx = [&](int i, int j)->int { return i * (n + 1) + j; };
int SZ = (n + 1) * (n + 1);
vector<int> mx1(SZ, 0), mx2(SZ, 0);
vector<int> mx_block(SZ, 0);
vector<char> check(SZ, 0);
unordered_map<long long, int> lastpos;
lastpos.reserve((size_t)n * m * 2 + 10);
ll ans = 0;
vector<int> cnt(V, 0);
vector<int> seen; seen.reserve(n);
const long long MUL = 1000LL;
for (int k = 1; k <= m; ++k)
{
for (int r = 1; r <= n; ++r)
{
int cur = 0;
for (int s = r; s >= 1; --s)
{
long long key = (long long)a[r][k] * MUL + s;
auto it = lastpos.find(key);
int last = (it == lastpos.end() ? 0 : it->second);
if (last > cur) cur = last;
mx1[idx(r, s)] = cur;
}
}
for (int r = 1; r <= n; ++r)
{
int cur = 0;
for (int s = r; s <= n; ++s)
{
long long key = (long long)a[r][k] * MUL + s;
auto it = lastpos.find(key);
int last = (it == lastpos.end() ? 0 : it->second);
if (last > cur) cur = last;
mx2[idx(r, s)] = cur;
}
}
for (int j = 1; j <= n; ++j)
for (int i = j + 1; i <= n; ++i)
if (mx1[idx(i - 1, j)] > mx1[idx(i, j)])
mx1[idx(i, j)] = mx1[idx(i - 1, j)];
for (int j = n; j >= 1; --j)
for (int i = j - 1; i >= 1; --i)
if (mx2[idx(i + 1, j)] > mx2[idx(i, j)])
mx2[idx(i, j)] = mx2[idx(i + 1, j)];
for (int i = 1; i <= n; ++i)
{
seen.clear();
bool ok = true;
for (int j = i; j <= n; ++j)
{
int v = a[j][k];
if (cnt[v] == 0) seen.push_back(v);
cnt[v]++;
if (cnt[v] > 1) ok = false;
check[idx(i, j)] = ok ? 1 : 0;
}
for (int v : seen) cnt[v] = 0;
}
for (int i = 1; i <= n; ++i)
{
for (int j = i; j <= n; ++j)
{
int &mx = mx_block[idx(i, j)];
if (!check[idx(i, j)]) mx = k;
if (mx1[idx(j, i)] > mx) mx = mx1[idx(j, i)];
if (mx2[idx(i, j)] > mx) mx = mx2[idx(i, j)];
ll width = k - mx;
if (width > 0)
{
ll area = 1ll * (j - i + 1) * width;
if (area > ans) ans = area;
}
}
}
for (int r = 1; r <= n; ++r)
{
long long key = (long long)a[r][k] * MUL + r;
lastpos[key] = k;
}
}
cout << ans;
}