您的位置:首页 > 其它

jzoj P1331 超级教主___dp+单调队列

2018-02-04 19:29 190 查看

题目大意:

LHX教主很能跳,跳需要消耗能量,每跳1米就会消耗1点能量。

教主为了收集能量,来到了一个神秘的地方,教主的正上方每100米处就有一个能量球(也就是这些能量球位于海拔100,200,300……米处),每个能量球所能提供的能量是不同的,一共有N个能量球(也就是最后一个能量球在N×100米处)。教主为了想收集能量,想跳着吃完所有的能量球。教主可以自由控制他每次跳的高度,接着他跳起把这个高度以下的能量球都吃了,他便能获得能量球内的能量,接着吃到的能量球消失。教主不会轻功,教主不会二段跳,所以教主不能因新吃到的能量而变化此次跳跃的高度。并且教主还是生活在地球上的,所以教主每次跳完都会掉下来。

问教主若要吃完所有的能量球,最多还能保留多少能量。

 

 对于10%的数据,有N≤10;

 对于20%的数据,有N≤100;

 对于40%的数据,有N≤1000;

 对于70%的数据,有N≤100000;

 对于100%的数据,有N≤2000000。

 保证对于所有数据,教主都能吃到所有的能量球,并且能量球包含的能量之和不超过2^31-1。

题解:

这题我们设f[i]表示跳完了前I所保留的最大能量

不难推出转移:

f[i]=max{f[j]+sum[I]-sum[j]-I*100}

没错时间复杂度是O(n^2)的!

所以肯定会TLE

我们要优化,因为转移时候,我们只需要找到f[j]-sum[j]的最大值转移过来就可以了,所以用单调队列

维护一下就可以了

时间复杂度:O(N)

代码:

var
cmax,sum,f:array [0..2000001] of longint;
head,tail,i,j,k,n,m,x:longint;

function max(aa,bb:longint):longint;
begin
if aa>bb then exit(aa);
exit(bb);
end;

begin
readln(n,f[0]);
cmax[1]:=0;
head:=1;
tail:=1;
for i:=1 to n do
begin
read(x);
sum[i]:=sum[i-1]+x;
while (head<=tail) and (f[cmax[head]]<i*100) do inc(head);
f[i]:=f[cmax[head]]+sum[i]-sum[cmax[head]]-i*100;
k:=f[i]-sum[i];
while (head<=tail) and (f[cmax[tail]]-sum[cmax[tail]]<=k) do dec(tail);
inc(tail);
cmax[tail]:=i;
end;
writeln(f
);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: