题意简述:有
n
天,每天股票都有一个交易价,每天可以买一股或卖一股或什么都不做。问n天最多能赚多少钱。
(1≤n≤100000)
题解:维护一个小根堆,堆里放可选的买进日交易价。对于每一天,比较小根堆顶交易价和当前日交易价。堆顶大的话,就直接把当前交易价压入队,表示这天什么都不做。堆顶小的话,就让堆顶那日买入,当前日卖出,赚一笔,把堆顶弹掉,把当前日交易价压两个进队。之所以这么做是为了支持撤销操作。之后这两个元素若是没有被弹出,就表示这日还是卖出;若是被弹出一个,就表示撤消了这次卖出操作,这日什么都不干;若是两个都被弹出,就是这个在这天买入股票。
var
heap,a:array[0..100050] of longint;
tot,n,s,i:longint;
ans:int64;
procedure swap(var a,b:longint);
var t:longint;
begin t:=a;a:=b;b:=t; end;
procedure heapup(x:longint);
begin
while ((x>1)and(heap[x]<heap[x>>1])) do
begin
swap(heap[x],heap[x>>1]);
x:=x>>1;
end;
end;
procedure heapdown(x:longint);
var
e:longint;
begin
while ((x<<1<=s)and(heap[x<<1]<heap[x])or(x<<1+1<=s)and(heap[x<<1+1]<heap[x])) do
begin
if ((x<<1+1<=s)and(heap[x<<1+1]<heap[x<<1]))
then e:=x<<1+1
else e:=x<<1;
swap(heap[x],heap[e]);
x:=e;
end;
end;
procedure poop;
begin
heap[1]:=heap[s];
dec(s);
heapdown(1);
end;
procedure push(x:longint);
begin
inc(s);
heap[s]:=x;
heapup(s);
end;
begin
assign(input,'trade.in');reset(input);
assign(output,'trade.out');rewrite(output);
tot:=0;
while not eof do
begin
read(n);inc(tot);s:=0;ans:=0;
if (n=0) then break;
for i:=1 to n do
read(a[i]);
for i:=1 to n do
if ((s>0)and(a[i]-heap[1]>0))
then
begin
inc(ans,a[i]-heap[1]);
poop;
push(a[i]);
push(a[i]);
end
else push(a[i]);
writeln('Case #',tot,': ',ans);
end;
close(input);close(output);
end.