bzoj 1597: [Usaco2008 Mar]土地购买 2011-12-27

1597: [Usaco2008 Mar]土地购买

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 697  Solved: 244
[Submit][Status][Discuss]

Description 农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要付5x5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费. Input* 第1行: 一个数: N * 第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽 Output* 第一行: 最小的可行费用. Sample Input4
100 1
15 15
20 5
1 100

输入解释:

共有4块土地.

Sample Output
500

HINT


FJ分3组买这些土地: 第一组:100x1, 第二组1x100, 第三组20x5 和 15x15 plot. 每组
的价格分别为100,100,300, 总共500.

Source

 

____________________________________________

 1 Program Stone;
 2 var i,j,n,bist,head,tail,insn:longint;
 3     len,wid,f,que:array[0..100000]of int64;
 4  Procedure kp(t,w:longint);
 5  var i,j:longint;
 6      k,ml,mw:int64;
 7   begin
 8    i:=t;j:=w;ml:=len[(t+w)div 2];mw:=wid[(t+w)div 2];
 9    repeat
10     while (len[i]>ml)or((len[i]=ml)and(wid[i]<mw)) do inc(i);
11     while (len[j]<ml)or((len[j]=ml)and(wid[j]>mw)) do dec(j);
12     if i<=j then begin
13                   k:=len[i];len[i]:=len[j];len[j]:=k;
14                   k:=wid[i];wid[i]:=wid[j];wid[j]:=k;
15                   inc(i);dec(j);
16                  end;
17    until i>j;
18    if i<w then kp(i,w);
19    if j>t then kp(t,j);
20   end;
21  function delhead(i,j,k:longint):boolean;
22   begin
23     if f[j]-f[k]>-wid[i]*(len[j+1]-len[k+1]) then exit(true) else exit(false);
24   end;
25  function deltail(i,j,k:longint):boolean;
26   begin
27     if (f[i]-f[j])*(len[j+1]-len[k+1])>(f[j]-f[k])*(len[i+1]-len[j+1]) then exit(true)
28                                                                        else exit(false);
29   end;
30 
31 Begin
32  assign(Input,'input.in');reset(input);
33   readln(n);
34   for i:=1 to n do
35    readln(len[i],wid[i]);
36   kp(1,n);
37   insn:=0;bist:=0;
38   for i:=1 to n do
39    begin
40     if wid[i]>bist then begin
41                          bist:=wid[i];
42                          inc(insn);
43                          len[insn]:=len[i];
44                          wid[insn]:=wid[i];
45                         end;
46    end;
47   n:=insn;
48   head:=0;tail:=0;
49   for i:=1 to n do
50    begin
51      while (tail>head)and(delhead(i,que[head],que[head+1])) do inc(head);
52      j:=que[head];
53      f[i]:=f[j]+wid[i]*len[j+1];
54      while (tail>head)and(deltail(i,que[tail],que[tail-1])) do dec(tail);
55      inc(tail);
56      que[tail]:=i;
57    end;
58   writeln(f[n]);
59  close(input);
60 end.
61 
62  

 

posted on 2016-03-02 20:20  Yesphet  阅读(169)  评论(0编辑  收藏  举报