首先按
为第一关键字,
为第二关键字,将没有贡献的矩形(
)删掉,这样就满足了
递增,
递减,列出dp方程
设
,状态
比
优,当且仅当
因为 递减,所以 ,那么
所以维护一个上凸壳,坐标为 ,斜率优化。
是单调的,所以单调队列维护
代码如下:
#include<algorithm>
#include<ctype.h>
#include<cstdio>
#define INF 21474836470000ll
#define N 50050
using namespace std;
typedef long long LL;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
int n,l,r,tot;
LL f[N];
struct Point{
LL x,y;
Point(){}
Point(LL _,LL __):x(_),y(__){}
}q[N],a[N],b[N],tmp;
inline bool cmp(Point a,Point b){
return a.x==b.x?a.y<b.y:a.x<b.x;
}
inline double Slop(Point a,Point b){
if(a.x==b.x) return a.y>b.y?-INF:INF;
return 1.0*(b.y-a.y)/(b.x-a.x);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
b[i].x=read();b[i].y=read();
}
sort(b+1,b+n+1,cmp);
for(int i=1;i<=n;i++){
while(tot && b[i].y>=a[tot].y) tot--;
a[++tot]=b[i];
}
l=r=0;
q[0]=Point(a[1].y,0);
for(int i=1;i<=tot;i++){
while(l<r && Slop(q[l],q[l+1])>-a[i].x) l++;
f[i]=a[i].x*q[l].x+q[l].y;
tmp=Point(a[i+1].y,f[i]);
while(l<r && Slop(q[r],tmp)>Slop(q[r-1],q[r])) r--;
q[++r]=tmp;
}
printf("%lld",f[tot]);
return 0;
}