可以转换成二分答案求最大连续子段和来做。

每次在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.