首先按
x
x
为第一关键字,为第二关键字,将没有贡献的矩形(
xi<xj,yi<yj,i<j
x
i
<
x
j
,
y
i
<
y
j
,
i
<
j
)删掉,这样就满足了
x
x
递增,递减,列出dp方程
fi=min{fj+yj+1∗xi}
f
i
=
m
i
n
{
f
j
+
y
j
+
1
∗
x
i
}
设
t>k
t
>
k
,状态
t
t
比优,当且仅当
因为 y y 递减,所以,那么
所以维护一个上凸壳,坐标为 (yi+1,fi) ( y i + 1 , f i ) ,斜率优化。
x x <script type="math/tex" id="MathJax-Element-1367">x</script>是单调的,所以单调队列维护
代码如下:
#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;
}