http://www.lydsy.com/JudgeOnline/problem.php?id=1597
给n块土地的长和宽,每组的购买价格为 长max∗宽max ,求最小花费
当一块土地的长和宽都小于等于另一块,那么它对结果就没有贡献,我们把它删掉
所以我们对长宽都降序排列,然后删掉没用的,长显然是递减的,宽肯定都是递增的(因为长是递减宽要是也是递减那后面的就是没用的)
我们得到转移方程
dp[i]=min{dp[j]+x[j+1,1]⋅x[i,2]} (0<=j<=i−1)
O(n2)
我们考虑斜率优化
假设 j<k且k更优
dp[j]+x[j+1,1]⋅x[i,2]>=dp[k]+x[k+1,1]⋅x[i,2]
dp[j]−dp[k]>=x[i,2]⋅(x[k+1,1]−x[j+1,1])
x[i,1]递减(x[k+1,1]−x[j+1,1])<0
dp[j]−dp[k]x[k+1,1]−x[j+1,1]<=x[i,2]
求最小值,所以维护队尾更新斜率小的值
const
maxn=50005;
var
x,y:array[0..maxn,1..2]of int64;
t:array[0..maxn]of longint;
dp:array[0..maxn]of int64;
i,j,k:longint;
n,m,tt,l,r:longint;
procedure sort(l,r:longint);
var i,j:longint; a,b,c:int64;
begin
i:=l; j:=r; a:=y[(l+r)>>1,1]; b:=y[(l+r)>>1,2];
repeat
while (y[i,1]>a)or((y[i,1]=a)and(y[i,2]>b)) do inc(i);
while (a>y[j,1])or((y[j,1]=a)and(y[j,2]<b)) do dec(j);
if not(i>j) then
begin
c:=y[i,1]; y[i,1]:=y[j,1]; y[j,1]:=c;
c:=y[i,2]; y[i,2]:=y[j,2]; y[j,2]:=c;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function check1(a,b,c:longint):boolean;
begin
exit((dp[b]-dp[a])<=x[c,2]*(x[a+1,1]-x[b+1,1]));
end;
function check2(a,b,c:longint):boolean;
begin
exit((dp[b]-dp[a])*(x[b+1,1]-x[c+1,1])>(dp[c]-dp[b])*(x[a+1,1]-x[b+1,1]));
end;
begin
readln(n);
for i:=1 to n do
readln(y[i,1],y[i,2]);
sort(1,n); {y}
m:=1; x[1,1]:=y[1,1]; x[1,2]:=y[1,2];
for i:=2 to n do
if (y[i,1]>x[m,1])or(y[i,2]>x[m,2])
then begin inc(m); x[m,1]:=y[i,1]; x[m,2]:=y[i,2]; end;
n:=m; dp[0]:=0;
l:=1; r:=1; t[1]:=0;
for i:=1 to n do
begin
while (l<r)and(check1(t[l],t[l+1],i)) do inc(l);
tt:=t[l];
dp[i]:=dp[tt]+x[tt+1,1]*x[i,2];
while (l<r)and(check2(t[r-1],t[r],i)) do dec(r);
inc(r); t[r]:=i;
end;
writeln(dp[n]);
end.