题目大意:
老师给小A布置了n项作业,每一项作业都有截止时间di和价值vi(你可以理解成每做完一份作业就要快递过去给老师,且快递是不耗费时间的),每完成一项作业便可获得其价值。但小A发现,自己每一个单位时间内只能完成其中的一项作业,请你告诉小A,他最多可以获得多少价值。
【数据规模与约定】
对于前30%的数据,n<=100.
对于前60%的数据,n<=1000,di<=n
对于100%的数据,n<=100000,di,vi<=1000000000.
题解:
排序+堆维护:
我们先对时间排序从小到大,快排、归排什么的都可以,冒泡,选排的话..
然后我们去维护一个小根堆
每次加入枚举到的一个i
di ≤ M 则看vi能否替换掉其堆顶,可以则替换然后维护
di > M 则将vi放到堆底,然后上移维护
M为堆内数的个数
最后这个小根堆里的值的总和就是最大价值
时间复杂度:O(N log N+M*log N)
var
d,v:array [0..100001] of longint;
rp:array [0..200001] of longint;
i,j,n,m:longint;
ans:int64;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
if l>=r then exit;
i:=l; j:=r;
mid:=d[(l+r) div 2];
repeat
while d[i]<mid do inc(i);
while d[j]>mid do dec(j);
if i<=j then
begin
d[0]:=d[i];d[i]:=d[j];d[j]:=d[0];
v[0]:=v[i];v[i]:=v[j];v[j]:=v[0];
inc(i); dec(j);
end;
until i>j;
qsort(i,r);
qsort(l,j);
end;
procedure up(x:longint);
begin
if x=1 then exit;
repeat
if rp[x]<rp[x div 2]
then begin
rp[0]:=rp[x];
rp[x]:=rp[x div 2];
rp[x div 2]:=rp[0];
end
else break;
x:=x div 2;
until x=0;
end;
procedure down(x:longint);
begin
if 2*x>m then exit;
repeat
x:=2*x;
if x+1<=m then
if rp[x]>rp[x+1] then inc(x);
if rp[x div 2]>rp[x] then
begin
rp[0]:=rp[x];
rp[x]:=rp[x div 2];
rp[x div 2]:=rp[0];
end
else break;
until 2*x>m;
end;
begin
readln(n);
for i:=1 to n do
readln(d[i],v[i]);
qsort(1,n);
m:=0;
for i:=1 to n do
begin
if d[i]<=m
then begin
if v[i]>rp[1] then
begin
rp[1]:=v[i];
down(1);
end
end
else begin
inc(m);
rp[m]:=v[i];
up(m);
end;
end;
ans:=0;
for i:=1 to m do
ans:=ans+rp[i];
writeln(ans);
end.