3.【最大连续和】sum
【题目描述】
输入一个长度为n的整数序列(A1,A2,……,An),从中找出一段连续的长度不超过M的子序列,使得这个序列的和最大
【输入格式】
第一行两个数n,m
接下来n行,每行一个数ai。
【输出格式】
一行,最大的满足条件的连续的长度不超过M的子序列。
【数据范围】
30%的数据:n<=3000,m<=100
100%的数据N,M<=1000000,-maxlongint<=ai<=maxlongint
【样例输入】
4 2
-1
3
–10
20
【样例输出】
20
思路:维护一个神奇的队列~队列记录sum[]的下标,sum[i]是前
i项和。维护队列递增,这样队首就是能取到范围内最小前i项和用
当前的sum[t]-sum[i]就是最大连续和,因此队列最大长度为m+1
程序:
var
q:array[1..1000000]of longint;
sum:array[0..1000000]of int64;
n,m,i,j:longint;
procedure init;
var
a:longint;
begin
sum[0]:=0;
readln(n,m);
for i:=1 to n do
begin
readln(a);
sum[i]:=sum[i-1]+a;
end;
end;
procedure doit;
var
h,t:longint;
ans:int64;
begin
ans:=sum[1];
h:=0;t:=1;
q[1]:=1;
for i:=2 to n do
begin
while i-q[h]>m do inc(h);
if sum[i]-sum[q[h]]>ans then ans:=sum[i]-sum[q[h]];
while (sum[i]<sum[q[t]])and(t>=h) do dec(t);
inc(t); q[t]:=i;
end;
writeln(ans);
end;
begin
assign(input,'sum.in');
assign(output,'sum.out');
reset(input);
rewrite(output);
init;
doit;
close(input);
close(output);
end.
反思:队列还可以这样用~