1 条题解
-
0
自动搬运
来自洛谷,原作者为

kkksc03
洛谷吉祥物 DA✩ZE搬运于
2025-08-24 21:24:53,当前版本为作者最后更新于2013-08-12 22:36:25,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
By tinylic
首先看出答案满足单调性,可以二分答案,转化为判定性问题。
令最优平均值为k,对于所有合法序列[l..r],
尝试将分式变为整式:s[l..r]>k*(r-l+1)无解。
移项,令b[i]=a[i]-k,s’[i]为b[1]..b[n]的和,则有
寻找长度在[s,t]内的子段和的最大值可以用单调队列解决,参考POJ2823。
这样就能通过O(n)的时间判定k是否可行,总复杂度O(nlogn)。
具体实现的细节参考标程。
#include <iostream> #include <cstdio> #include <cstdlib> #define maxn 100010 using namespace std; int n, s, t, i; double l, r, mid, ans; double a[maxn]; int b[maxn]; double sum[maxn]; int q[maxn]; bool check(double x) { int i, l = 1, r = 0; for (i = 1; i <= n; i++) a[i] = (double)b[i] - x; sum[0] = 0; for (i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i]; for (i = 1; i <= n; i++) { if (i >= s) { while (r >= l && sum[i - s] < sum[q[r]]) r--; q[++r] = i - s; } if (l <= r && q[l] < i - t) l++; if (l <= r && sum[i] - sum[q[l]] >= 0) return true; } return false; } int main() { scanf("%d", &n); scanf("%d%d", &s, &t); for (i = 1; i <= n; i++) scanf("%d", &b[i]); ans = l = -10000; r = 10000; while (r - l > 1e-5) { mid = (l + r) / 2; if (check(mid)) ans = l = mid; else r = mid; } printf("%.3lf\n", ans); return 0; }
- 1
信息
- ID
- 413
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者