当前位置: 首页 > news >正文

题目 3217 ⭐成绩统计⭐【滑动窗口 + 二分搜索】蓝桥杯2024年第十五届省赛

小蓝的班上有 n n n 个人,一次考试之后小蓝想统计同学们的成绩,第 i 名同学的成绩为 a i a_i ai 。当小蓝统计完前 x x x 名同学的成绩后,他可以从 1 ∼ x 1 ∼ x 1x 中选出任意 k k k 名同学的成绩,计算出这 k k k 个成绩的方差。小蓝至少要检查多少个人的成绩,才有可能选出 k k k 名同学,他们的方差小于一个给定的值 T T T

提示: k k k 个数 v 1 , v 2 , ⋯   , v k v_1, v_2, \cdots, v_k v1,v2,,vk 的方差 σ 2 σ^2 σ2 定义为: σ 2 = ∑ k i = 1 ( v i − v ′ ) / k σ^2=∑ k_i=1(v_i−v')/k σ2=ki=1(viv)/k ,其中 v ′ v' v 表示 v v v 的平均值, v ′ = ∑ k i = 1 v i k v'=∑k_{i=1} \frac{v_i}{k} v=ki=1kvi

关键点

  1. 问题目标:找到最小的 x x x,使得在前 x x x 名同学的成绩中,存在一个大小为 k k k 的子集,其方差小于 T T T

  2. 方差的含义

    • 方差越小,说明数据越集中。
    • 如果选择的 k k k 个数非常接近,方差会很小。
  3. 解决思路

    • 对前 x x x 名同学的成绩排序。
    • 使用 滑动窗口 检查所有连续的 k k k 个数的方差是否小于 T T T
    • 通过 二分搜索 找到最小的 x x x
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

// 计算 k 个数的方差
double calculateVariance(const vector<int>& nums, int start, int k) {
    double sum = 0;
    for (int i = start; i < start + k; i++) {
        sum += nums[i];
    }
    double mean = sum / k; // 平均值
    double variance = 0;
    for (int i = start; i < start + k; i++) {
        variance += (nums[i] - mean) * (nums[i] - mean);
    }
    return variance / k;
}

// 检查前 x 个数中是否存在 k 个数的方差小于 T
bool check(const vector<int>& a, int x, int k, double T) {
    vector<int> subset(a.begin(), a.begin() + x); // 取前 x 个数
    sort(subset.begin(), subset.end()); // 排序
    for (int i = 0; i <= x - k; i++) { // 滑动窗口
        double variance = calculateVariance(subset, i, k);
        if (variance < T) {
            return true;
        }
    }
    return false;
}

// 二分搜索找到最小的 x
int findMinX(const vector<int>& a, int k, double T) {
    int n = a.size();
    int left = k, right = n; // x 的最小值是 k,最大值是 n
    int result = n + 1; // 初始化为一个不可能的值
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (check(a, mid, k, T)) {
            result = mid; // 更新结果
            right = mid - 1; // 尝试更小的 x
        } else {
            left = mid + 1; // 尝试更大的 x
        }
    }
    return result <= n ? result : -1; // 如果找到返回 x,否则返回 -1
}

复杂度分析

  • 时间复杂度:

    • 排序: O ( x   l o g   x ) O(x\ log\ x) O(x log x),其中 x x x 是检查的人数
    • 滑动窗口检查方差: O ( x ) O(x) O(x)
    • 二分搜索: O ( l o g   n ) O(log\ n) O(log n)
    • 总复杂度 O ( n l o g   n ⋅ l o g n ) O(nlog\ n⋅logn) O(nlog nlogn)
  • 空间复杂度:

    • 存储子集: O ( n ) O(n) O(n)

总结

  • 通过排序和滑动窗口,可以高效地检查是否存在满足条件的子集。
  • 二分搜索用于快速找到最小的 x x x
  • 该方法在时间和空间复杂度上都是可行的,适用于中等规模的数据。

相关文章:

  • 大白话 CSS 中transform属性的常见变换类型(平移、旋转、缩放等)及使用场景
  • 管理 SELinux 安全性
  • 正则表达式详解
  • android13打基础: timepicker控件
  • Vue 3 ref(new Map()) 无法触发watch
  • 力扣35.搜索插入位置-二分查找
  • Linux网络配置(超详细)
  • 「Java EE开发指南」如何用MyEclipse构建一个Web项目?(二)
  • Go权限管理库Casbin和身份验证库jwt-go初试
  • 【2025】Electron + React 架构筑基——从零到一的跨平台开发
  • 电子学会—2024年12月青少年软件编程(图形化)四级等级考试真题——趣味点阵屏
  • 当中国“智算心跳”与全球共振:九章云极DataCanvas首秀MWC 2025
  • 快速掌握EasyOCR应用实战指南
  • Qt常用控件之表格QTableWidget
  • openharmony 软总线-设备发现流程
  • OSPF网络类型:NBMA与P2MP
  • K8s 1.27.1 实战系列(七)Deployment
  • 第八节:基于Winform框架的串口助手小项目---完结优化《C#编程》
  • HTML 属性(详细易懂)
  • Manus全球首个通用Agent,Manus AI:Agent应用的ChatGPT时刻
  • 医院网站建设策划/抖音指数查询
  • 网上推广是什么意思/seo外包费用
  • 营销方案 网站/云南百度公司
  • 佛山网站建设哪个好点/百度搜索引擎优化
  • web网站百度不收录吗/深圳抖音推广公司
  • app网站及其特色/软文推广代理平台