斜率优化 [Usaco2008 Mar]土地购买

orz..一开始没看数据范围,这题长*宽后要用int64

方程f[i]=min{f[k]+x[i]*y[k+1]}

可以用斜率优化

然后维护一个凸包,可以用单调队列维护每次斜率最优的

program tt;
var n,i,tail,l,r:longint;
    q,f,a,b:array[0..50000]of int64;
    
procedure qsort(x,y:longint);//a上升,b下降
var i,j,mid,mid1,t:longint;
begin
 i:=x;j:=y;
 mid:=a[(x+y) div 2];
 mid1:=b[(x+y) div 2];
 repeat
  while (a[i]<mid)or(a[i]=mid)and(b[i]>mid1) do i:=i+1;
  while (a[j]>mid)or(a[j]=mid)and(b[j]<mid1) do j:=j-1;
  if i<=j then
   begin
    t:=a[i];a[i]:=a[j];a[j]:=t;
    t:=b[i];b[i]:=b[j];b[j]:=t;
    i:=i+1;
    j:=j-1;
   end;
 until i>j;
 if i<y then qsort(i,y);
 if x<j then qsort(x,j);
end;
begin
 read(n);
 for i:=1 to n do
  read(a[i],b[i]);
 qsort(1,n);

 tail:=1;
 for i:=2 to n do
  begin
   while (tail>0)and(b[i]>=b[tail]) do tail:=tail-1;
   tail:=tail+1;
   b[tail]:=b[i];a[tail]:=a[i];
  end;
 n:=tail;
 for i:=0 to n-1 do b[i]:=b[i+1];
 l:=1;r:=1;f[0]:=0;q[1]:=0;
 for i:=1 to n do
  begin
   while (l<r) and (a[i]*(b[q[l]]-b[q[l+1]])>f[q[l+1]]-f[q[l]]) do
    l:=l+1;
   f[i]:=f[q[l]]+b[q[l]]*a[i];
   //处理队尾
   while (l<r) and ((f[i]-f[q[r-1]])*(b[q[r]]-b[i])>=(f[i]-f[q[r]])*(b[q[r-1]]-b[i])) do  //相当于凸包
    r:=r-1;
   r:=r+1;
   q[r]:=i;
  end;
 writeln(f[n]);
end.


 

你可能感兴趣的:(斜率优化 [Usaco2008 Mar]土地购买)