【贪心】游戏通关

  游戏通关

背景

  机房里的人都十分认真地在编程,但总有一些人会偷偷玩游戏。。。。。。

问题描述

     XY 经常在机房里偷偷玩游戏,于是他也经常被CJH 教练批评。但屡次的批评一点作用也没有,你看他又开始玩起了游戏。

  这次XY 可碰上难题了,因为据可靠的线报CJH 教练在不久后就回来机房,但XY 需要完成N 个任务才能将这个游戏通关。

  每个任务完成时限T,就是这个任务必须在时间T 之前完成(你可以认为游戏刚开始的时间为1),还有完成这个任务XY 可以获得一定的奖励W。由于XY 娴熟的技术以及任务的简单,他可以在一个单位时间将任务完成。

  XY 想要在CJH 教练到来之前将任务全部完成,同时他也想获得最多的奖励。这个他本来可以编程自己完成的,但是为了能马上将游戏通关,他需要全神贯注进去。于是他没有空编程计算,于是他希望你能帮助他将问题的答案计算出来。

输入格式

  输入数据第一行有一个整数N ,表示需要完成的任务数目;

  接下来N  行,每行两个整数T,W  (中间用一个空格隔开),分别表示完成这个任务的最后期限和完成这个任务后获得的奖励。

输出格式

  输出数据有且仅有一行,只包含一个整数S,表示最多获得的奖励。

样例输入                            样例输出

Sample #1

game.in                              game.out

2                                          5

1 5

1 4

Sample #2

game.in                              game.out

5                                          15

2 3

1 2

4 5

1 3

3 4

样例解释

  对于样例2 XY 可以选择完成任务1,3,4 和5,这样他可以获得奖励15。

数据规模

对于10%的数据,N≤100,Ti≤100,Wi≤2000;

对于30%的数据,N≤1000,Ti≤5000,Wi≤2000;

对于50%的数据,N≤10000,Ti≤20000,Wi≤2000;

对于100%的数据,N≤200000,Ti≤200000,Wi≤2000 。

时间限制

1s

=========================

贪心题

===================

方法一:

开队列【n^2{50分}】

------------------------

type
  node=record
         t,w:longint;
       end;
var
  n:longint;
  a:array[1..200000]of node;
 //f:array[1..200000]of boolean;
  dui:array[0..200000]of longint;
procedure init;
begin
  assign(input,'game.in');
  assign(output,'game.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure qsort(s,t:longint);
var
  i,j:longint;
  x:node;
  tem:node;
begin
  i:=s; j:=t;
  x:=a[(s+t)shr 1];
  repeat
    while (x.t<a[j].t) or ((x.t=a[j].t)and(x.w<a[j].w)) do dec(j);
    while (a[i].t<x.t) or ((x.t=a[i].t)and(x.w>a[i].w)) do inc(i);
    if i<=j then
      begin
        tem:=a[i]; a[i]:=a[j]; a[j]:=tem;
        inc(i); dec(j);
      end;
  until i>j;
  if i<t then qsort(i,t);
  if s<j then qsort(s,j);
end;

procedure main;
var
  i:longint;
  point:longint;
  ans:longint;
  l,r,k:longint;
begin
  readln(n);
  for i:=1 to n do readln(a[i].t,a[i].w);
  qsort(1,n);
  point:=1;

  //fillchar(f,sizeof(f),true);
  fillchar(dui,sizeof(dui),0);
  //时间的队列.
  l:=a[n].t;
  for i:=n downto 1 do  //枚举任务..
    begin
      if a[i].w>dui[a[i].t] then
        //如果当前点>他所在的那个时刻的点的值的话
        //更新他所在的那个时刻的点..
        begin
          if l>a[i].t then l:=a[i].t;
          for r:=l-1 to a[i].t-1  do dui[r]:=dui[r+1];
          if l>1 then l:=l-1;
          dui[a[i].t]:=a[i].w;
        end
        else
        begin
          for r:=a[i].t downto 1 do
            if dui[r]<a[i].w then break;
          k:=r;
          for r:=l-1 to r-1 do
            dui[r]:=dui[r+1];
          if l>1 then l:=l-1;
          if dui[k]<a[i].w then dui[k]:=a[i].w;
        end;
    end;
  ans:=0;
  for i:=1 to a[n].t do ans:=ans+dui[i];
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.


___________________________________________________________________

方法二:

堆【100分】:

-------------------

type
  node=record
          t,w:longint;
       end;
var
  n:longint;
  a:array[1..200000]of node;
  dui:array[0..200000]of longint;
  dui_s:longint;
procedure init;
begin
  assign(input,'game.in');
  assign(output,'game.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure qsort(s,t:longint);
var
  i,j:longint;
  x:longint;
  tem:node;
begin
  i:=s; j:=t;
  x:=a[(s+t)shr 1].t;
  repeat
    while x<a[j].t do dec(j);
    while a[i].t<x do inc(i);
    if i<=j then
      begin
        tem:=a[i];
        a[i]:=a[j];
        a[j]:=tem;
        inc(i); dec(j);
      end;
  until i>j;
  if i<t then qsort(i,t);
  if s<j then qsort(s,j);
end;

procedure adjust_up(r:longint);
var
  k:longint;
  tem:longint;
begin
  k:=r shr 1;
  while (k>0)and(dui[k]<dui[r]) do
    begin
      tem:=dui[k];
      dui[k]:=dui[r];
      dui[r]:=tem;
      r:=k;
      k:=r shr 1;
    end;
end;

procedure shift(r,n:longint);
var
  k:longint;
  tem:longint;
begin
  k:=2*r;
  if (k+1<=n)and(dui[k+1]>dui[k]) then inc(k);
  while (k<=n) and (dui[k]>dui[r]) do
    begin
      tem:=dui[k];
      dui[k]:=dui[r];
      dui[r]:=tem;
      r:=k;
      k:=2*r;
      if (k+1<=n)and(dui[k+1]>dui[k]) then inc(k);
    end;
end;

procedure main;
var
  i:longint;
  num:longint;
  ans:longint;
begin
  readln(n);
  for i:=1 to n do
    readln(a[i].t,a[i].w);
  qsort(1,n);
  num:=n;
  dui_s:=0;
  ans:=0;
  for i:=a[n].t downto 1 do
    begin
      while (num>0)and(a[num].t=i) do
        begin
          inc(dui_s);
          dui[dui_s]:=a[num].w;
          adjust_up(dui_s);
          dec(num);
        end;
      if dui_s>0 then
        begin
          ans:=ans+dui[1];
          dui[1]:=dui[dui_s];
          dec(dui_s);
          shift(1,dui_s);
        end;
    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.


 ________________________________

方法三:

并查集【100分】

-------------

type
  node=record
          t,w:longint;
       end;
var
  n:longint;
  a:array[1..200000]of node;
  fa,f:array[0..200000]of longint;
  dui_s:longint;
procedure init;
begin
  assign(input,'game.in');
  assign(output,'game.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure qsort(s,t:longint);
var
  i,j:longint;
  x:longint;
  tem:node;
begin
  i:=s; j:=t;
  x:=a[(s+t)shr 1].w;
  repeat
    while x>a[j].w do dec(j);
    while a[i].w>x do inc(i);
    if i<=j then
      begin
        tem:=a[i];
        a[i]:=a[j];
        a[j]:=tem;
        inc(i); dec(j);
      end;
  until i>j;
  if i<t then qsort(i,t);
  if s<j then qsort(s,j);
end;

function find(x:longint):longint;
begin
  if fa[x]=x then exit(x)
             else begin fa[x]:=find(fa[x]); exit(fa[x]); end;
end;

procedure merge(a,b:longint);
begin
  a:=find(a);
  b:=find(b);
  fa[a]:=b;
end;

procedure main;
var
  i:longint;
  ans:longint;
begin
  readln(n);
  for i:=1 to n do
    readln(a[i].t,a[i].w);
  qsort(1,n);
  //按价值从大到小排序
  ans:=0;
  for i:=0 to 200000 do fa[i]:=i;
  fillchar(f,sizeof(f),0);
  for i:=1 to n do
    begin
      if find(a[i].t)<>0 then
        begin
          ans:=ans+a[i].w;
          merge(find(a[i].t),find(a[i].t)-1);
        end;
    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.


 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值