知识点:二分,最大连续子列和
这个题可以用二分做,是最大化,判定的时候就是将分式乘过来,转化为判定,有不小于某长度的子列和大于等于0,这个判定其实就是求最大子列和,由于数据的问题,需要线性的算法,用前缀和可以实现,这个不论最大值是不是负数都适用的方法,然后这道题的实现上我费了好多时间,一个是用for还是while循环,这个我用for就不对,用while才能过,还是想不明白,然后就是输出的时候是输出l还是r,这个也是会一个过一个不过,总之这个精度问题现在还是头大
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pa;
const int N = 1e5 + 5;
const double EPS = 1e-5;
int n, k;
double a[N], s[N];
bool check(double x) {
for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i] - x;
double Max = -1e10;
double Min = 1e10;
for (int i = k; i <= n; i++) {
Min = min(Min, s[i - k]);
Max = max(Max, s[i] - Min);
}
return Max >= 0;
}
void solve(double l, double r) {
while (r - l > EPS) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%d", (int) (r * 1000));
}
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) scanf("%lf", &a[i]);
solve(-1000000, 1000000);
return 0;
}