题意:1000000000个单位时间,给定n个工作和各自的截止时间和利润,每在截止时间之前(或当天)完成工作即可获得该工作的利润,问最大获得的利润是多少
经典贪心
把截止时间从小到大排序,对我们选择完成的工作的利润维护一个小根堆。
从1到n扫,能完成当前工作就完成,并将该工作的利润插入小根堆中;
如果不能完成,判断该工作的利润是否大于我们选择完成的工作的最小利润(小根堆堆顶),如果大于则替换掉原最小利润工作,否则无操作
const
day=1000000000;
type
rec=record
d,p:longint;
end;
var
heap :array[0..100010] of longint;
n,now,size :longint;
ans :int64;
i :longint;
a :array[0..100010] of rec;
procedure sort(l,r:longint);
var
i,j,x:longint;
y:rec;
begin
i:=l; j:=r; x:=a[(l+r)>>1].d;
while (i<=j) do
begin
while (a[i].d<x) do inc(i);
while (a[j].d>x) do dec(j);
if (i<=j) then
begin
y:=a[i]; a[i]:=a[j]; a[j]:=y;
inc(i); dec(j);
end;
end;
if i<r then sort(i,r);
if j>l then sort(l,j);
end;
procedure swap(var a,b:longint);
var
c:longint;
begin
c:=a; a:=b; b:=c;
end;
procedure heap_up(x:longint);
begin
if x=1 then exit;
while x<>1 do
begin
if heap[x]<heap[x div 2] then
begin
swap(heap[x],heap[x div 2]);
x:=x div 2;
end else break;
end;
end;
procedure heap_down(x:longint);
var
tt:longint;
begin
while (2*x<=size) do
begin
if heap[2*x]<heap[x] then tt:=2*x else tt:=x;
if 2*x+1<=size then
if heap[2*x+1]<heap[tt] then tt:=2*x+1;
if x<>tt then
begin
swap(heap[x],heap[tt]);
x:=tt;
end else break;
end;
end;
begin
read(n);
for i:=1 to n do read(a[i].d,a[i].p);
sort(1,n);
now:=0; ans:=0; size:=0;
for i:=1 to n do
begin
if now+1<=a[i].d then
begin
inc(size);
inc(now);
inc(ans,int64(a[i].p));
heap[size]:=a[i].p;
heap_up(size);
end else
if a[i].p>heap[1] then
begin
dec(ans,int64(heap[1]));
inc(ans,int64(a[i].p));
heap[1]:=a[i].p;
heap_down(1);
end;
end;
writeln(ans);
end.
——by Eirlys