SSL P2670 作业

来源:互联网 发布:北京编程培训学校 编辑:程序博客网 时间:2024/06/16 09:52

题目大意:
老师给小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.