思路:
滑动窗体维护的是i-ed~i-st的序列,且序列按照前缀和单调递增,队首前缀和最小
代码:
#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
using namespace std;
typedef long long ll;
typedef pair<double, int> PII;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int mod = 998244353;
int n, st, ed;
double a[N];
double check(double ave)
{
double b[N];
b[0] = 0;
for (int i = 1; i <= n; i++)
b[i] = a[i] - ave + b[i - 1]; //将前缀和都减去ave
int q[N];
double ans = -1e8;
int h = 0, t = -1;
//单调队列求长度为st~ed之间的最大子串和
for (int i = 1; i <= n; i++)
{
while (h <= t && q[h] < i - ed) //若目前长度超过ed则删队列头元素
h++;
if (i >= st)
{
while (h <= t && b[q[t]] >= b[i - st]) //若i-st的前缀和小于尾部前缀和则删去尾部前缀和,队列维护单调递减前缀和
t--;
q[++t] = i - st;
ans = max(ans, b[i] - b[q[h]]);
}
}
return ans;
}
int main()
{
fastio;
cin >> n >> st >> ed;
for (int i = 1; i <= n; i++)
cin >> a[i];
double l = -1e4, r = 1e4;
while (r - l > eps)
{
double mid = (l + r) / 2;
double t = check(mid);
if (t > 0)
l = mid;
else
r = mid;
}
cout << fixed << setprecision(3) << l << endl;
return 0;
}