链接
题目描述
给定正整数序列A ,求一个平均数最大的,长度不小于 L 的(连续的)子段。
样例输入
10 6
6
4
2
10
3
8
5
9
4
1
样例输出
6500
思路
显然二分 (那要不然为啥是二分练习题呢
我们二分出这个平均值
然后把数列中每个数都减去这个平均值
然后找是否有一段长度不小于L的且和不为负数的数段即可
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int n, L;
double l, r, lq;
double b[100050], a[100050], sum[100005];
bool check(double x)
{
for(int i = 1; i <= n; ++i) b[i] = a[i] - x;
for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + b[i];
double ans = -1e9;
double minx = 1e9;
for(int i = L; i <= n; ++i)
{
minx = min(minx, sum[i - L]);
ans = max(ans, sum[i] - minx);
}
return ans >= 0;
}
int main()
{
scanf("%d%d", &n, &L);
for(int i = 1; i <= n; ++i)
scanf("%lf", &a[i]);
l = -1e6; r = 1e6;//经过实测,0~2000可以A
while(l <= r)
{
double mid = (l + r) / 2;
if(!check(mid)) r = mid - 1e-5, lq = mid;
else l = mid + 1e-5;//按精度来加减
}
printf("%d", int(lq * 1000));
return 0;
}