首先发现如果一个矩形被另一个矩形完全包含,则它一定不会对答案有贡献。
因此使用单调栈 $O(n)$ 处理出有用的矩形,应该是个阶梯状的东西。
之后 $O(n^2)$ DP 是简单的。然而它直接过了。
不过 双倍经验 是过不去的。
所以考虑优化,发现这东西看上去就很斜率,所以干就完了。
两维都递增,可以直接队头转移。
#include <bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
const int M = 5e4 + 15;
int n;
PII a[M], stk[M];
int top = 0;
bool cmp(PII a, PII b) {
if (a.first != b.first) return a.first < b.first;
return a.second > b.second;
}
int x[M], y[M];
long long dp[M];
int q[M], st, ed;
double X(int p) { return -y[p]; }
double Y(int p) { return dp[p - 1]; }
double slope(int a, int b) {
return (Y(a) - Y(b)) * 1.0 / (X(a) - X(b));
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d%d", &a[i].first, &a[i].second);
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++) {
while (top && stk[top].second <= a[i].second) top--;
stk[++top] = a[i];
}
for (int i = 1; i <= top; i++) x[i] = stk[i].first, y[i] = stk[i].second;
// for (int i = 1; i <= top; i++) cout << x[i] << ' ' << y[i] << endl;
dp[0] = 0;
dp[1] = x[1] * 1ll * y[1];
st = ed = 1; q[st] = 1;
for (int i = 2; i <= top; i++) {
dp[i] = dp[i - 1] + x[i] * 1ll * y[i];
while (st < ed && slope(q[st], q[st + 1]) <= x[i]) st++;
int j = q[st];
dp[i] = min(dp[i], dp[j - 1] + x[i] * 1ll * y[j]);
while (st < ed && slope(q[ed - 1], q[ed]) >= slope(q[ed], i)) ed--;
q[++ed] = i;
// for (int j = st; j <= ed; j++) cout << q[j] <<' '; puts("");
}
printf("%lld\n", dp[top]);
return 0;
}