P1419 寻找段落
题目描述
给定一个长度为 nnn 的序列 aaa,定义 aia_iai 为第 iii 个元素的价值。现在需要找出序列中最有价值的“段落”。段落的定义是长度在 [S,T][S, T][S,T] 之间的连续序列。最有价值段落是指平均值最大的段落。
段落的平均值 等于 段落总价值 除以 段落长度。
输入格式
第一行一个整数 nnn,表示序列长度。
第二行两个整数 SSS 和 TTT,表示段落长度的范围,在 [S,T][S, T][S,T] 之间。
第三行到第 n+2n+2n+2 行,每行一个整数表示每个元素的价值指数。
输出格式
一个实数,保留 333 位小数,表示最优段落的平均值。
输入输出样例 #1
输入 #1
3
2 2
3
-1
2
输出 #1
1.000
说明/提示
【数据范围】
对于 30%30\%30% 的数据有 n≤1000n \le 1000n≤1000。
对于 100%100\%100% 的数据有 1≤n≤1000001 \le n \le 1000001≤n≤100000,1≤S≤T≤n1 \le S \le T \le n1≤S≤T≤n,−104≤ai≤104-{10}^4 \le a_i \le {10}^4−104≤ai≤104。
【题目来源】
tinylic 改编
C++实现
#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;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
用C++实现信奥 P1419 寻找段落&spm=1001.2101.3001.5002&articleId=155259072&d=1&t=3&u=4f36ecb9e40b43a1b38bfd500786b434)
354

被折叠的 条评论
为什么被折叠?



