JSOI2007建筑抢修

实际上和大多这类题一样(比如wikioi上的地鼠游戏),考察的都是堆的操作

这次改完之后就算把堆的模版定下来了

悲剧的是:大根堆打成了小根堆,导致一开始一直是10分……

按结束时间排序,(经过验证,结束时间相同的建筑不需要在根据t的大小来排序)

如果time+t[i]<=p[i] 那么直接将它加入堆中

如果上面的条件不满足,取出堆中的最大元素,如果time-a[1]+t[i]<=p[i] 那么将a[1]替换为t[i]

这样是因为这使得总完成任务数没变,但总时间却缩小了,不会比原来的决策差

代码:

 1 var  i,n,cnt,time:longint;
 2      p,t,a:array[0..200000] of longint;
 3 procedure put(x:longint);
 4  var i,k:longint;
 5  begin
 6    inc(cnt);
 7    i:=cnt;k:=i>>1;
 8    while k>=1 do
 9     begin
10       if a[k]<x then begin a[i]:=a[k];i:=k;k:=k>>1;end
11       else k:=0;
12     end;
13    a[i]:=x;
14  end;
15 procedure get(x:longint);
16  var i,k:longint;
17  begin
18    i:=1;k:=i<<1;
19    while k<=cnt do
20     begin
21       if (k<cnt) and (a[k+1]>a[k]) then inc(k);
22       if a[k]>x then begin a[i]:=a[k];i:=k;k:=k<<1;end
23       else k:=cnt+1;
24     end;
25    a[i]:=x;
26  end;
27 procedure sort(h,l:longint);
28  var i,j,x,y,temp:longint;
29  begin
30    i:=h;j:=l;x:=p[(i+j)>>1];y:=t[(i+j)>>1];
31    repeat
32      while (p[i]<x) do inc(i);
33      while (p[j]>x) do dec(j);
34      if i<=j then
35       begin
36         temp:=p[i];p[i]:=p[j];p[j]:=temp;
37         temp:=t[i];t[i]:=t[j];t[j]:=temp;
38         inc(i);dec(j);
39       end;
40    until i>j ;
41    if i<l then sort(i,l);
42    if j>h then sort(h,j);
43  end;
44 procedure init;
45  begin
46    readln(n);
47    for i:=1 to n do readln(t[i],p[i]);
48    sort(1,n);
49  end;
50 procedure main;
51  begin
52    time:=0;
53    cnt:=0;
54    for i:=1 to n do
55     begin
56       if time+t[i]<=p[i] then
57         begin
58           put(t[i]);inc(time,t[i]);continue;
59         end;
60       if (time-a[1]+t[i]<=p[i]) and (t[i]<a[1]) then
61         begin
62           inc(time,t[i]-a[1]);get(t[i]);continue;
63         end;
64     end;
65    writeln(cnt);
66  end;
67 begin
68   init;
69   main;
70 end.                  
View Code

 

JSOI2007建筑抢修,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。