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

【二分查找、滑动窗口】P10389 [蓝桥杯 2024 省 A] 成绩统计|普及+

本文涉及的基础知识点

C++二分查找
C++算法:滑动窗口及双指针总结

[蓝桥杯 2024 省 A] 成绩统计

题目描述

小蓝的班上有 n n n 个人,一次考试之后小蓝想统计同学们的成绩,第 i i i 名同学的成绩为 a i a_i ai。当小蓝统计完前 x x x 名同学的成绩后,他可以从 1 ∼ x 1 \sim 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 \sigma^2 σ2 定义为: σ 2 = ∑ i = 1 k ( v i − v ˉ ) 2 k \sigma^2=\dfrac {\sum_{i=1}^k(v_i-\bar v)^2} k σ2=ki=1k(vivˉ)2,其中 v ˉ \bar v vˉ 表示
v i v_i vi 的平均值, v ˉ = ∑ i = 1 k v i k \bar v = \dfrac {\sum_{i=1}^k v_i} k vˉ=ki=1kvi

输入格式

输入的第一行包含三个正整数 $n, k, T $,相邻整数之间使用一个空格分隔。

第二行包含 n n n 个正整数 a 1 , a 2 , ⋯   , a n a_1, a2, \cdots, a_n a1,a2,,an ,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。如果不能满足条件,输出 − 1 -1 1

样例 #1

样例输入 #1

5 3 1
3 2 5 2 3

样例输出 #1

4

提示

检查完前三名同学的成绩后,只能选出 $3, 2, 5 $,方差为 $1.56 $;

检查完前四名同学的成绩后,可以选出 $3, 2, 2 $,方差为 $0.22 < 1 $,所以答案为 $4 $。

对于 10 % 10\% 10% 的评测用例,保证 1 ≤ n , k ≤ 1 0 2 1 ≤ n, k ≤ 10^2 1n,k102
对于 30 % 30\% 30% 的评测用例,保证 1 ≤ n , k ≤ 1 0 3 1 ≤ n, k ≤ 10^3 1n,k103
对于所有评测用例,保证 $1 ≤ n, k ≤ 10^5 $,$1 ≤ T ≤ 2
^{31} -1 $,$1 ≤ a_i ≤ n $。

二分查找+滑动窗口

令平均成绩是vv,成绩依次是v1到vk。则方差的平方是: ∑ i : 1 k ( v v − v i ) 2 = k v v 2 − 2 v v ∑ i : 1 k v i + ∑ i : 1 k v i 2 \sum_{i:1}^k(vv-vi)^2=kvv^2-2vv\sum_{i:1}^kvi+\sum_{i:1}^kvi^2 i:1k(vvvi)2=kvv22vvi:1kvi+i:1kvi2
对a1到an升序排序。某最优解包括ai,且ai最小,则a[i…i+k-1]一定是不劣解。证明过程比较复杂,
二分类型:寻找首端
参数范围:[k,n]
Check函数:依次计算a[i…i+k-1]的方差是否小于等于L。任意一个小于等于返回真,否则返回false。
需要判断是否无解,无解返回-1。
获取配时:需要全局变量
编译时:需要全局变量
执行时:清空配方
性质一:最大值减少后,仍然大于等于平均值,则方差变小或不变。
令平均成绩是aa,bi = ai-aa,显然sum(b)=0
令bk减少kd,bk >= kd
最后一项减少前减去减少后:bk^2 - (bk-kd)^2 = 2bkkd-kdkd
其它k-1项某项减少前减去减少后:bi2-(bi-d)2 = 2bid-d^2
相加:2bk(k-1)d+2sum(b)d-kdkd-(k-1)dd 因为sum(b)为0,故:
2bk(k-1)d-kdkd-(k-1)dd
因为d>0,约去d
2bk(k-1)-kkd+(k-1)d
bk>=kd
2kd(k-1)-kkd +(k-1)d
约去d
2kk-2k-kk+k-1
= kk-k-1
当k >1是,式子大于等于0,故减少kd是不劣解。
当k==0时,方差恒定1,也是不劣解。
本题证明:
令某解最小成绩ai,最大成绩aj,ak没有选择, a i ≤ a k ≤ a j ai \leq ak \leq aj aiakaj
如果ak >= aa,则根据性质一,aj替换aj。
如果ak < aa,则 将a进行如下变换 a[i] = x-(a[i]-x) ,再按性质一互换。

代码

核心代码

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>

#include <bitset>
using namespace std;

template<class T = int>
vector<T> Read() {
	int n;
	scanf("%d", &n);
	vector<T> ret(n);
	for(int i=0;i < n ;i++) {
		cin >> ret[i];
	}
	return ret;
}

template<class T = int>
vector<T> Read(int n) {
	vector<T> ret(n);
	for (int i = 0; i < n; i++) {
		cin >> ret[i];
	}
	return ret;
}

string ReadChar(int n) {
	string str;
	char ch;
	while (n--) {
		do
		{
			scanf("%c", &ch);
		} while (('\n' == ch));
			str += ch;
	}
	return str;
}
template<class T1,class T2>
void ReadTo(pair<T1, T2>& pr) {
	cin >> pr.first >> pr.second;
}

template<class INDEX_TYPE>
class CBinarySearch
{
public:
	CBinarySearch(INDEX_TYPE iMinIndex, INDEX_TYPE iMaxIndex, INDEX_TYPE tol = 1) :m_iMin(iMinIndex), m_iMax(iMaxIndex), m_iTol(tol) {}
	template<class _Pr>
	INDEX_TYPE FindFrist(_Pr pr)
	{
		auto left = m_iMin - m_iTol;
		auto rightInclue = m_iMax;
		while (rightInclue - left > m_iTol)
		{
			const auto mid = left + (rightInclue - left) / 2;
			if (pr(mid))
			{
				rightInclue = mid;
			}
			else
			{
				left = mid;
			}
		}
		return rightInclue;
	}
	template<class _Pr>
	INDEX_TYPE FindEnd(_Pr pr)
	{
		INDEX_TYPE leftInclude = m_iMin;
		INDEX_TYPE right = m_iMax + m_iTol;
		while (right - leftInclude > m_iTol)
		{
			const auto mid = leftInclude + (right - leftInclude) / 2;
			if (pr(mid))
			{
				leftInclude = mid;
			}
			else
			{
				right = mid;
			}
		}
		return leftInclude;
	}
protected:
	const INDEX_TYPE m_iMin, m_iMax, m_iTol;
};

class Solution {
		public:
			int Ans(vector<int>&a ,int k,long long T) {
				T *= k;
				const int N = a.size();		
				auto Check = [&](int mid) {
					double sum1=0, sum2 = 0;
					vector<int> b(a.begin() , a.begin() + mid);
					sort(b.begin(), b.end());
					for (int i = 0; i < b.size(); i++) {
						sum1 += b[i];
						sum2 += (double)b[i] * b[i];
						if (i >= k) {
							sum1 -= b[i - k];
							sum2 -= (double)b[i - k] * b[i - k];
						}
						if (i < k - 1) { continue; }
						const double avg = sum1 / k;
						const double cur = (k * avg * avg - 2 * sum1 * avg + sum2);
						if (cur <= T) { return true; }
					}
					return false;
				};
				auto ans= CBinarySearch<int>(k, N).FindFrist(Check);
				return Check(ans) ? ans : -1;
			}
		};

int main() {
#ifdef _DEBUG
	freopen("a.in", "r", stdin);
#endif // DEBUG
	int N, K,T;
	cin >> N >> K >> T ;
	auto a = Read<int>(N);
#ifdef _DEBUG	
	/*printf("N=%d,K=%d,T=%d,", N, K,T);
	Out(a, "a=");*/
#endif	
	auto res = Solution().Ans(a,K,T);
	cout << res << std::endl;
	return 0;
}

单元测试

int N, K,T;
		vector<int> a;
		TEST_METHOD(TestMethod11)
		{
			N = 5, K = 3, T = 1, a = { 3,2,5,2,3 };
			auto res = Solution().Ans(a,K,T);
			AssertEx(4, res);
		}
		TEST_METHOD(TestMethod12)
		{
			N = 5, K = 3, T = 0, a = { 3,2,5,2,3 };
			auto res = Solution().Ans(a, K, T);
			AssertEx(-1, res);
		}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

相关文章:

  • ROS2 Rviz 实战:给 panda 机械臂场景塞个圆柱体
  • Win7重装不翻车!ISO镜像安全下载渠道+BIOS设置避雷手册
  • `label` 标签的 `for` 属性详解
  • Nacos高频面试题10个
  • Mybatis的优缺点
  • 苹果商店上架流程,app上架发布流程
  • supervisord管理Gunicorn进程,使用Nginx作为反向代理运行flask web项目
  • 【无监督学习】层次聚类步骤及matlab实现
  • SQL语句执行顺序是什么?
  • Linux之SO_REUSEPORT属性笔记
  • 牛客周赛 Round 83
  • 996引擎-问题处理:实现自定义道具变身卡
  • R语言——数据类型
  • Embedding技术:DeepWalkNode2vec
  • 开发社交陪玩app小程序
  • 三口插头 接线定义
  • 【Ubuntu】Vim 9.1.0821 编译安装
  • 【论文分享】推理大模型Post-Training技术的全面综述
  • Android Framework 常见面试题
  • 前端基础入门-高级
  • 做好公司网站/网站seo
  • 做网站建设网站制作/100个免费推广b站
  • 成都新都网站开发/网上商城推广13种方法
  • 拼多多刷单网站开发/今日西安头条最新消息
  • 网站做ppt模板/什么叫做关键词
  • 怎么做浏览网站的小程序/下载百度极速版