題意
給你n個數和一個數字k,要求所有長度的所有連續子序列中,平均值最大的值。
思路
設數組代表序列的前綴和,所求的平均值即爲
這個值即是直線的斜率。
需要注意要保證單調隊列的隊首元素即是對於每種情況的最優解。同時維護的是一個下凸殼。
要注意這個題需要快速讀入。需要快速讀入的板子。
代碼
//
// Created by yjq on 2019/9/19.
//
#include <bits/stdc++.h>
//#include <cstdio>
//#include <cstring>
//#include <iostream>
//#include <algorithm>
using namespace std;
#define ll long long
//#define ld long double
//#define ull unsigned long long
//#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
ll n, k;
inline char nc() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline bool _read(ll &sum) {
char ch = nc();
if (ch == EOF)
return 0;
sum = 0;
while (!(ch >= '0' && ch <= '9'))ch = nc();
while (ch >= '0' && ch <= '9')sum = sum * 10 + ch - 48, ch = nc();
return sum;
}
const int maxn = 1e5 + 10;
ll a[maxn], s[maxn], q[maxn];
//inline int X(int i, int j) {
// return j - i;
//}
//inline int Y(int i, int j) {
// return s[j] - s[i];
//}
//inline double DP(int i, int j) {
// return (double) (s[i] - s[j]) / (double) (i - j);
//}
int main() {
// __;
while (_read(n) && _read(k)) {
for (int i = 1; i <= n; ++i) {
_read(s[i]);
s[i] += s[i - 1];
}
/* while (cin >> n >> k) {
for (int i = 1; i <= n; ++i) {
cin >> s[i];
s[i] += s[i - 1];
}*/
int l = 0, r = 0;
q[++r] = 0;
double ans = 0;
for (int i = 1; i <= n; ++i) {
int cur = i - k + 1;
while (l + 1 < r && (s[i] - s[q[l + 1]]) * (i - q[l + 2]) <= (i - q[l + 1]) * (s[i] - s[q[l + 2]]))
++l;
if (i < k)continue;
ans = max(ans, (double) (s[i] - s[q[l + 1]]) / (double) (i - q[l + 1]));
while (l + 1 < r &&
(s[q[r]] - s[q[r - 1]]) * (cur - q[r]) >=
(q[r] - q[r - 1]) * (s[cur] - s[q[r]]))
--r;
q[++r] = cur;
}
printf("%.2f\n", ans);
}
return 0;
}