bzoj 1029 贪心+堆

25 篇文章 0 订阅
6 篇文章 0 订阅

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

Sample Output

3

HINT

Source



先按t2排序 一定要先排序,不然会影响到now,也就是说,会出现一种情况,就是如果先修它就可以修,而不排序的话就不能修

原则:修补时间能多就多,能短就短(因为越短才可能修的越来越多)
所以我们需要一个大根堆来记录我们选择修得建筑的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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值