Description
小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的
入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全
毁坏。现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需
要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。如果某个建筑在一
段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多
的建筑。
Input
第一行是一个整数N接下来N行每行两个整数T1,T2描述一个建筑:修理这个建筑需要T1秒,如果在T2秒之内还
没有修理完成,这个建筑就报废了。
Output
输出一个整数S,表示最多可以抢修S个建筑.N < 150,000; T1 < T2 < maxlongint
Sample Input
4
100 200
200 1300
1000 1250
2000 3200
100 200
200 1300
1000 1250
2000 3200
Sample Output
3
HINT
Source
原则:修补时间能多就多,能短就短(因为越短才可能修的越来越多)
所以我们需要一个大根堆来记录我们选择修得建筑的t1,来保证在多的前提下尽可能的缩短修的总时间,即让我们选择修的建筑t1最大的最小
排序后,判断一个建筑能不能修,先看能否完成,可以的话就直接修,然后把t1加入大根堆中;如果不能修,判断它的t1是否比大根堆堆顶(选择修的最大t1)小,如果小的话就替换
思想类似于求最长上升子序列的O(nlogn)的优化
var
n,now,size :longint;
i :longint;
heap :array[0..150010] of longint;
t1,t2 :array[0..150010] of longint;
procedure swap(var a,b:longint);
var
c:longint;
begin
c:=a;a:=b;b:=c;
end;
procedure heap_down(i:longint);
var
t:longint;
begin
while (2*i<=size) do
begin
if (heap[2*i]>heap[i]) then t:=2*i else t:=i;
if (i*2+1<=size) then
if (heap[2*i+1]>heap[t]) then t:=2*i+1;
if (t<>i) then
begin
swap(heap[i],heap[t]);
i:=t;
end else exit;
end;
end;
procedure heap_up(i:longint);
var
t:longint;
begin
while (i>1) do
begin
if (heap[i div 2]<heap[i]) then t:=i div 2 else t:=i;
if (t<>i) then
begin
swap(heap[t],heap[i]);
i:=t;
end else exit;
end;
end;
procedure sort(l,r:longint);
var
i,j:longint;
x:longint;
begin
i:=l;j:=r;x:=t2[(l+r) >>1];
while (i<=j) do
begin
while (t2[i]<x) do inc(i);
while (t2[j]>x) do dec(j);
if (i<=j) then
begin
swap(t2[i],t2[j]);
swap(t1[i],t1[j]);
inc(i);dec(j);
end;
end;
if (i<r) then sort(i,r);
if (j>l) then sort(l,j);
end;
begin
read(n);
size:=0;now:=0;
for i:=1 to n do read(t1[i],t2[i]);
sort(1,n);
for i:=1 to n do
begin
if (t2[i]>=now+t1[i]) then
begin
inc(size);
heap[size]:=t1[i];
inc(now,t1[i]);
heap_up(size);
end else
begin
if (t1[i]<heap[1]) and (size<>0) then
begin
now:=now-heap[1]+t1[i];
heap[1]:=t1[i];
heap_down(1);
end;
end;
end;
writeln(size);
end.
——by Eirlys