可以转换成二分答案求最大连续子段和来做。
每次在a[i]的基础上减去二分出来的答案。
求出长度不小于f的最大连续子段和。如果大于0,则调整下边界,否则调整上边界。
求长度不小于f的最大连续子段和需要一些小技巧,比如说判断以i为终点的连续子段和,就可以看sum[i]-sum[i-f]+dp[i-f]的正负。其中dp[i]表以i为终点的最大连续子段和。具体见代码。
Program cowfnc;//By_Thispoet
Const
maxn=100005;
Var
i,j,k,m,n,f,ans :Longint;
l,r,mid :Longint;
a,dp,sum,b :Array[0..maxn]of Int64;
Function Max(i,j:Longint):Longint;
begin
if i>j then exit(i);exit(j);
end;
Function Check(i:Longint):Boolean;
var j,k:Longint;
begin
for j:=1 to n do b[j]:=a[j]-i;
for j:=1 to n do dp[j]:=Max(0,dp[j-1]+b[j-1]);
for j:=1 to n do sum[j]:=sum[j-1]+b[j];
for j:=1 to n-f+1 do
if sum[j+f-1]-sum[j-1]+dp[j]>=0 then exit(true);
exit(false);
end;
BEGIN
readln(n,f);
r:=0;
for i:=1 to n do
begin
readln(a[i]);
a[i]:=a[i]*1000;
r:=Max(r,a[i]);
end;
l:=0;
while l<=r do
begin
mid:=(l+r)>>1;
if check(mid) then
begin
ans:=mid;
l:=mid+1;
end else r:=mid-1;
end;
writeln(ans);
END.