白细胞计数

GitHub跳转原题关系图返回列表

线性扫描找出最大、最小值并求和,扣除两端后求平均值,再扫描有效样本找最大绝对偏差。

OJ: roj

题目 ID: 1114

难度:入门

标签:模拟线性扫描

创建: 2026-09-29 19:26

更新: 2026-10-05 02:16

题目描述

医院采集了 nn 份白细胞样本(2<n≤3002<n\le 300),去掉一个最大值和一个最小值后,把剩余 n−2n-2 个有效样本的平均值作为分析指标,并输出有效样本与该平均值之差绝对值的最大值。 输入第一行 nn,随后 nn 行每行一个浮点数;输出保留两位小数的平均值和误差,样例输入 5 12.0 13.0 11.0 9.0 10.0,输出 11.00 1.00。

思路

一次扫描求出总和 SS、最大值 MM、最小值 mm,得平均值 xˉ=(S−M−m)/(n−2)\bar{x}=(S-M-m)/(n-2);再扫描一遍,对所有不等于 MM 和 mm 的样本求 ∣ai−xˉ∣|a_i-\bar{x}| 的最大值,时间复杂度 O(n)O(n)。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2025-11-28 15:41
# update_at: 2025-11-28 15:41

import sys


def solve() -> None:
    data = iter(map(float, sys.stdin.buffer.read().split()))
    n = int(next(data))
    vals = [next(data, 0.0) for _ in range(n)]  # 同步 std.cpp 读到 EOF 后的零填充

    mx, mn = max(vals), min(vals)
    avg = (sum(vals) - mx - mn) / (n - 2)
    err = max(abs(x - avg) for x in vals if x not in (mx, mn))

    print(f"{avg:.2f} {err:.2f}")


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 02:16
 * update_at: 2026-10-05 02:16
 */
// main.cpp:去掉一个最大值和一个最小值后求平均,再求有效样本与平均值的最大绝对偏差。
#include <cstdio>
#include <algorithm>

typedef long long ll;

const int MAXN = 305;
double a[MAXN]; // a[1..n] 保存 n 份白细胞样本

int main() {
    ll n;
    if (scanf("%lld", &n) != 1) {
        return 0;
    }

    // 逐份读入样本;读不到时按 0.0 补足,保持与原题评测数据一致
    for (ll i = 1; i <= n; i++) {
        if (scanf("%lf", &a[i]) != 1) {
            a[i] = 0.0;
        }
    }

    // 一次扫描求最大值、最小值和总和
    double max_value = a[1];
    double min_value = a[1];
    double total = 0.0;
    for (ll i = 1; i <= n; i++) {
        if (a[i] > max_value) {
            max_value = a[i];
        }
        if (a[i] < min_value) {
            min_value = a[i];
        }
        total += a[i];
    }

    double average = (total - max_value - min_value) / (n - 2);

    // 再扫描一次,求有效样本(不等于最大值也不等于最小值)与平均值的最大偏差
    double error = 0.0;
    for (ll i = 1; i <= n; i++) {
        if (a[i] == max_value || a[i] == min_value) {
            continue;
        }
        double diff = a[i] - average;
        if (diff < 0.0) {
            diff = -diff;
        }
        if (diff > error) {
            error = diff;
        }
    }

    printf("%.2f %.2f\n", average, error);
    return 0;
}