斜率dp,主要是结合求下凸包的性质
#include <STDIO.H>
#include <STRING.H>
#include <algorithm>
using namespace std;
/*
dp[i] = max{(sum[i]-sum[j])/(i-j) } (i-j >= k)
等于点(i,sum[i])与点(j,sum[j])间的斜率
斜率dp
每次更新i时,更新凸包
*/
const int MAXN = 100005;
inline double max(double a, double b)
{
return a>b?a:b;
}
double sum[MAXN];
int q[MAXN];
double input()
{
char c;
double res = 0.0;
do
{
c = getchar();
} while ( c < '0' || c > '9');
do
{
res = res*10 + (c - '0');
c = getchar();
} while ( c >= '0' && c <= '9');
return res;
}
double cross(int a, int b, int c)
{
return (sum[b]-sum[a])*(c-a) - (sum[c]-sum[a])*(b-a);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int n, k;
int i, j;
int head;
while (scanf("%d%d", &n, &k) == 2)
{
sum[0] = 0.0;
for (i = 1; i<= n; ++i)
sum[i] = sum[i-1]+input();
double res = 0, tp;
head = 0;
q[head++] = 0; // 从0开始
for (i = k; i<= n; ++i)
{
j = i-k; // 更新最短距离处的点
while (head>1 && cross(q[head-2],q[head-1],j)>0)
--head;
q[head++] = j;
// 二分寻找最大值
int mid;
int a, b;
a = 0, b = head-1;
while (a < b)
{
mid = (a+b)>>1;
if (cross(q[mid],q[mid+1],i) > 0)
b = mid;
else
a =mid+1;
}
tp = (sum[i]-sum[q[a]])/(i-q[a]);
res = max(res, tp);
}
printf("%.2lf\n", res);
}
return 0;
}