46 lines
1.4 KiB
C++
46 lines
1.4 KiB
C++
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
const int N = 100010;
|
||
const int INF = 0x3f3f3f3f;
|
||
int n, F; // n,数字个数,m:区间长度
|
||
double a[N], s[N];
|
||
|
||
bool check(double avg) {
|
||
for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i] - avg;
|
||
double x = 0;
|
||
for (int k = F; k <= n; k++) { // 枚举右端点
|
||
/*
|
||
一维前缀和公式: s[l,r]=s[r]-s[l-1]
|
||
左端点的所有可能值l∈[1,k-F+1]
|
||
① s[l,r]= s[r]-s[0]
|
||
② s[l,r]= s[r]-s[k-F+1-1]=s[r]-s[k-F]
|
||
*/
|
||
x = min(x, s[k - F]); // 记录左侧不断更新的最小值
|
||
if (s[k] - x >= 0) return true; // 如果s[k]减去前面的最小值大于0,就不必理其它的位置值了
|
||
}
|
||
// 如果所有右端点都枚举完,每个右端点都无法找出左端点最小值,使得区间和大于0,就是都白费
|
||
return false;
|
||
}
|
||
|
||
int main() {
|
||
scanf("%d%d", &n, &F); // F:区间长度
|
||
|
||
double l = 2000, r = 0;
|
||
for (int i = 1; i <= n; i++) { // 求前缀和,数组下标从1开始
|
||
scanf("%lf", &a[i]);
|
||
l = min(l, a[i]); // l是平均值的最小值
|
||
r = max(r, a[i]); // r是平均值的最大值
|
||
}
|
||
|
||
while (r - l > 1e-5) { // 浮点数二分模板
|
||
double mid = (l + r) / 2;
|
||
if (check(mid))
|
||
l = mid;
|
||
else
|
||
r = mid;
|
||
}
|
||
|
||
printf("%d\n", (int)(r * 1000));
|
||
|
||
return 0;
|
||
} |