bzoj1597

首先不难想到排序,这种无规律的东西一般都要转化为有规律才好做

首先以x为第一关键字,y为第二关键字升序排序

拍完序我们发现,若存在两块土地i,j

x[i]<=x[j],y[i]<=y[j],那么土地i的购买一定可以忽略(因为价格是由x,y的乘积决定的)

剔除掉不需考虑的土地,不难发现剩下的土地x是升序而y是降序的

然后就可以dp了

f[i]=min(f[k]+x[i]*y[k+1]); (0<=k<=i-1)

显然这个是很容易用斜率优化的,不多说了

 1 var q,st:array[0..50010] of longint;
 2     x,y,f:array[0..50010] of int64;
 3     w,n,t,h,r,i:longint;
 4 
 5 procedure swap(var a,b:int64);
 6   var c:longint;
 7   begin
 8     c:=a;
 9     a:=b;
10     b:=c;
11   end;
12 
13 procedure sort(l,r: longint);
14   var i,j: longint;
15       p,q:int64;
16   begin
17     i:=l;
18     j:=r;
19     p:=x[(l+r) shr 1];
20     q:=y[(l+r) shr 1];
21     repeat
22       while (x[i]<p) or (x[i]=p) and (y[i]<q) do inc(i);
23       while (p<x[j]) or (p=x[j]) and (q<y[j]) do dec(j);
24       if not(i>j) then
25       begin
26         swap(x[i],x[j]);
27         swap(y[i],y[j]);
28         inc(i);
29         j:=j-1;
30       end;
31     until i>j;
32     if l<j then sort(l,j);
33     if i<r then sort(i,r);
34   end;
35 
36 function check(l,r:longint):double;
37   begin
38     check:=(f[l]-f[r])/(y[st[r+1]]-y[st[l+1]]);
39   end;
40 
41 begin
42   readln(n);
43   for i:=1 to n do
44     readln(x[i],y[i]);
45   sort(1,n);
46   t:=1;
47   st[1]:=1;
48   for i:=2 to n do
49   begin
50     while (t>0) and (x[i]>=x[st[t]]) and (y[i]>=y[st[t]]) do dec(t);
51     inc(t);
52     st[t]:=i;
53   end;
54   f[0]:=0;
55   r:=0;
56   h:=0;
57   for i:=1 to t do
58   begin
59     while (h<r) and (check(q[h+1],q[h])<=x[st[i]]) do inc(h);
60     w:=q[h];
61     f[i]:=f[w]+y[st[w+1]]*x[st[i]];
62     while (h<r) and (check(i,q[r])<check(q[r],q[r-1])) do dec(r);
63     inc(r);
64     q[r]:=i;
65   end;
66   writeln(f[t]);
67 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473166.html