背景
机房里的人都十分认真地在编程,但总有一些人会偷偷玩游戏。。。。。。
问题描述
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.