拿到手的时候根本想不到是斜率优化。。。然而思路太神了。
对于两块地x1*y1 x2*y2,如果x1<=x2 && y1<=y2,那么前一块地就可以忽略掉,所以我们先按x1升序排序,然后做一遍类似单调队列的操作把所有可以忽略的地块去掉。
这样我们可以得出平方级别的DP方程:
现在开始斜率优化:
假设j>k且j优于k,那么满足
化简得到
然后就随便写写呗~
虽然各种奇葩错误WA了无数次
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <cstdlib>
using namespace std;
#define ll long long
const int N=50005;
struct arr{
ll x,y;
}b[N],a[N];
ll n,m,q[N],l,r;
ll f[N];
bool cmp(const arr A,const arr B){
if (A.x==B.x) return A.y>B.y;
return A.x<B.x;
}
ll getX(ll x,ll y){
return a[y+1].y-a[x+1].y;
}
ll getY(ll x,ll y){
return f[x]-f[y];
}
int main(){
scanf("%lld",&n);
for (ll i=1;i<=n;i++)
scanf("%lld%lld",&b[i].x,&b[i].y);
sort(b+1,b+n+1,cmp);
for (ll i=1;i<=n;i++){
while (m && b[i].y>=a[m].y) m--;
a[++m]=b[i];
}
q[0]=l=r=0;
for (ll i=1;i<=m;i++){
while (l<r && getY(q[l+1],q[l])<=a[i].x*getX(q[l+1],q[l])) l++;
ll j=q[l];
f[i]=f[j]+a[j+1].y*a[i].x;
while (l<r && getY(q[r],q[r-1])*getX(i,q[r])>=getY(i,q[r])*getX(q[r],q[r-1])) r--;
q[++r]=i;
for (int i=1;i<=n;i++)
}
printf("%lld\n",f[m]);
return 0;
}