二分判定,这个题在poj上面提交,g++超时,c++过了,不明白,然后二分的外层循环,写成是for的话,一直出错,不明白为什么,然后最后的答案要选r,不然也有可能出错,还是不明白为什么,
至于题目本身的模型可以概括成,序列里面找长度不小于L的最大连续子列和,之前单调队列的是找长度不超过L的最大连续子列和,相同之处都是转化成前缀和扫描完成的,
本题还有一个很关键的地方就是判定的时候减去平均值,这样转化为序列和大于等于0,不需要除以一个数,这个是很关键的,
#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#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, l;
double a[N], b[N], sum[N];
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 min_t = 10000000;
double ans = -10000000;
for (int i = l; i <= n; i++) {
if (sum[i - l] < min_t) min_t = sum[i - l];
ans = max(ans, sum[i] - min_t);
}
return ans >= 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) floor(r * 1000));
}
int main() {
cin >> n >> l;
for (int i = 1; i <= n; i++) cin >> a[i];
solve(0, 2000);
return 0;
}