【2024蓝桥杯/C++/A组/成绩统计】

题目

代码

#include<bits/stdc++.h>
using namespace std;

// 定义长整型变量的简写
#define ll long long

// 常量N定义为10万加10
const int N = 1e5+10;

// 定义变量n,k,t为长整型
ll n, k ,t;
// 定义avg和tmp为浮点型
float avg;
float tmp;
// 定义长度为N的数组a和b,存储输入的数据和排序后的数据
ll a[N], b[N];
// 定义长度为N的数组sum和sum2,分别用于累计求和以及平方和
ll sum[N];
ll sum2[N];

// 函数check用来检查在前num个数中是否存在k个数的方差小于t
bool check(ll num)
{
    // 复制数组a到数组b中
    for (int i = 1; i <= num; i++) b[i] = a[i];
    // 对数组b中的前num个元素进行排序
    sort(b+1, b+1+num);

    // 计算累加和以及累加平方和
    for(int i = 1; i <= num; i++)
    {
        sum[i] = sum[i-1] + b[i];
        sum2[i] = sum2[i-1] + b[i]*b[i];
    }
    // 从第k个元素开始遍历,计算均值与方差
    for(int i = k; i <= num; i++)
    {
        // 计算均值
        avg = 1.0*(sum[i] - sum[i-k]) / k;
        // 计算方差
        tmp = sum2[i] - sum2[i-k];
        // 如果方差小于t,则返回true
        if(tmp/k - avg*avg < t) return true;
    }

    // 如果没有找到符合条件的子序列,则返回false
    return false;
}

// 主函数
int main()
{
    // 输入n,k,t
    cin >> n >> k >> t;

    // 读取输入的n个整数,并同时复制到数组b中
    for(int i = 1; i <= n; i++) cin >> a[i], b[i] = a[i];

    // 初始化二分查找的左界l,右界r
    int l = k, r = n, mid;
    // 执行二分查找
    while(l < r)
    {
        // 计算中间位置
        mid = (l+r) >> 1;
        // 如果中间位置的子序列方差小于t,则将右界更新为mid
        if(check(mid)) r = mid;
        // 否则将左界更新为mid+1
        else l = mid+1;
    }

    // 如果最终的左右边界相同并且不符合条件,则输出-1
    if(l == r && !check(r)) cout << -1;
    // 否则输出最终的答案
    else cout << r;
    return 0;
}

注意

不能一次性排序,而要不断加长不断排序。因为前后者产生出的k长连续序列是不同的。

avg的计算必须有1.0,因为avg的产生涉及除法,而各操作数都是非浮点数;tmp的计算则不然,不涉及除法所以不用1.0,之后tmp参与除法,此时tmp已经是浮点数则不需要1.0。一言以蔽之就是浮点数的产生计算中,如果涉及除法且各个操作数都不是浮点数,则要用1.0。

这里采用了排序、二分和前缀和。

  • 19
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值