先特判掉一整行和一整列顶满的状态。
然后考虑极大化矩形面积,一定是边框压着关键点最优。
所以枚举每个点作为开头,以 $y$ 坐标排序,并向右扫更新上下边界。
如果 $x_j \lt x_i$ 就更新 $up$,否则更新 $down$。
说句闲话,这题貌似是 DP 题,但是写成了一个类似于悬线法的东西……
#include <bits/stdc++.h>
using namespace std;
const int N = 5015;
struct node {
int x, y;
} a[N];
bool cmp1(node a, node b) {
return a.x < b.x;
}
int k, n, m;
bool cmp2(node a, node b) {
return a.y < b.y;
}
long long ans = 0;
int main() {
scanf("%d%d%d", &m, &n, &k);
for (int i = 1; i <= k; i++) scanf("%d%d", &a[i].y, &a[i].x);
a[++k] = (node){0, 0}, a[++k] = (node){n, 0}, a[++k] = (node){0, m}, a[++k] = (node){n, m};
sort(a + 1, a + 1 + k, cmp1);
for (int i = 1; i < k; i++) ans = max(ans, m * 1ll * (a[i + 1].x - a[i].x));
sort(a + 1, a + 1 + k, cmp2);
for (int i = 1; i < k; i++) ans = max(ans, n * 1ll * (a[i + 1].y - a[i].y));
for (int i = 1; i <= k; i++) {
int up = 0, dn = n;
for (int j = i + 1; j <= k; j++) {
if (a[j].y == a[i].y) continue;
ans = max(ans, (a[j].y - a[i].y) * 1ll * (dn - up));
if (a[j].x < a[i].x) up = max(up, a[j].x);
if (a[j].x >= a[i].x) dn = min(dn, a[j].x);
}
}
for (int i = k; i >= 1; i--) {
int up = 0, dn = n;
for (int j = i - 1; j >= 1; j--) {
if (a[j].y == a[i].y) continue;
ans = max(ans, (a[i].y - a[j].y) * 1ll * (dn - up)); //what??? a[j].y - a[i].y ??
if (a[j].x < a[i].x) up = max(up, a[j].x);
if (a[j].x >= a[i].x) dn = min(dn, a[j].x);
}
}
printf("%lld\n", ans);
return 0;
}