[BZOJ1597] [Usaco2008 Mar]土地购买

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1597

题目大意

给n块土地的长和宽,每组的购买价格为 maxmax ,求最小花费

题解

当一块土地的长和宽都小于等于另一块,那么它对结果就没有贡献,我们把它删掉
所以我们对长宽都降序排列,然后删掉没用的,长显然是递减的,宽肯定都是递增的(因为长是递减宽要是也是递减那后面的就是没用的)
我们得到转移方程
dp[i]=min{dp[j]+x[j+1,1]x[i,2]}   (0<=j<=i1)
O(n2)
我们考虑斜率优化
假设 j<kk
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.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值