news 2026/6/9 2:32:31

NOIP2009普及组真题解析:用C++三种排序方法搞定‘分数线划定’(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NOIP2009普及组真题解析:用C++三种排序方法搞定‘分数线划定’(附完整代码)

NOIP2009普及组真题解析:用C++三种排序方法搞定‘分数线划定’(附完整代码)

在信息学奥赛(NOIP/CSP)的备考过程中,排序算法是最基础也是最重要的知识点之一。2009年NOIP普及组的"分数线划定"题目,不仅考察了选手对排序算法的理解和应用能力,更提供了一个绝佳的机会来比较不同排序方法在实际问题中的表现。本文将通过这道经典题目,深入解析C++中三种不同的排序实现方案:标准库sort、手写冒泡排序以及计数排序+插入排序的组合应用。

1. 题目分析与解题思路

"分数线划定"题目要求根据考生的成绩和报名号,确定面试的分数线和进入面试的考生名单。具体规则是:面试人数为计划录取人数的150%(向下取整),然后所有成绩不低于该分数线的考生都将进入面试。如果有多人成绩相同,则按报名号升序排列。

这道题的核心在于多重条件排序:首先按成绩降序排列,成绩相同则按报名号升序排列。对于最多5000个考生的数据规模,虽然O(n²)的排序算法也能胜任,但不同实现方式在代码复杂度、可读性和潜在性能上都有显著差异。

提示:在实际竞赛中,理解题目要求并选择合适的算法往往比直接编码更重要。建议先花1-2分钟仔细分析题目条件和数据范围。

2. 标准库sort解法:简洁高效的首选

C++标准库中的sort函数基于快速排序实现,平均时间复杂度为O(n log n),是解决这类排序问题的首选方案。下面是使用sort的完整实现:

#include <bits/stdc++.h> using namespace std; #define N 5005 struct Student { int id, score; }; bool compare(const Student &a, const Student &b) { return a.score != b.score ? a.score > b.score : a.id < b.id; } int main() { Student students[N]; int n, m; cin >> n >> m; for(int i = 0; i < n; ++i) cin >> students[i].id >> students[i].score; sort(students, students + n, compare); int cutoff = students[(int)(m * 1.5) - 1].score; int count = 0; while(count < n && students[count].score >= cutoff) count++; cout << cutoff << " " << count << endl; for(int i = 0; i < count; ++i) cout << students[i].id << " " << students[i].score << endl; return 0; }

这种实现方式的优势在于:

  • 代码简洁:利用结构体和比较函数,清晰地表达了排序规则
  • 性能优越:标准库sort经过高度优化,处理5000个元素几乎瞬间完成
  • 可读性强:逻辑清晰,易于理解和维护

3. 手写冒泡排序:理解算法本质

虽然在实际比赛中很少需要手写排序算法,但通过实现冒泡排序可以深入理解排序的基本原理。下面是冒泡排序的实现:

#include <bits/stdc++.h> using namespace std; #define N 5005 int main() { int ids[N], scores[N], n, m; cin >> n >> m; for(int i = 0; i < n; ++i) cin >> ids[i] >> scores[i]; // 冒泡排序实现 for(int i = 0; i < n - 1; ++i) { for(int j = 0; j < n - 1 - i; ++j) { if(scores[j] < scores[j+1] || (scores[j] == scores[j+1] && ids[j] > ids[j+1])) { swap(scores[j], scores[j+1]); swap(ids[j], ids[j+1]); } } } int cutoff = scores[(int)(m * 1.5) - 1]; int count = 0; while(count < n && scores[count] >= cutoff) count++; cout << cutoff << " " << count << endl; for(int i = 0; i < count; ++i) cout << ids[i] << " " << scores[i] << endl; return 0; }

冒泡排序的特点:

  • 时间复杂度:O(n²),对于n=5000来说,理论最大操作次数约为2500万次
  • 稳定性:通过适当实现可以保证稳定性(相等元素相对顺序不变)
  • 教学价值:帮助理解基本排序原理和交换操作

4. 计数排序+插入排序:特定场景的优化

当成绩范围有限(如0-100分)时,可以采用计数排序+插入排序的组合方案:

#include <bits/stdc++.h> using namespace std; vector<int> students[101]; // 按分数分组存储报名号 int main() { int n, m, id, score; cin >> n >> m; for(int i = 0; i < n; ++i) { cin >> id >> score; // 使用插入排序保持每个分数段内报名号有序 auto &group = students[score]; auto it = lower_bound(group.begin(), group.end(), id); group.insert(it, id); } int total = 0, cutoff = 0; for(int s = 100; s >= 0; --s) { total += students[s].size(); if(total >= m * 1.5) { cutoff = s; break; } } // 重新计算实际人数(可能有更多人达到cutoff分数) total = 0; for(int s = 100; s >= cutoff; --s) total += students[s].size(); cout << cutoff << " " << total << endl; for(int s = 100; s >= cutoff; --s) for(int id : students[s]) cout << id << " " << s << endl; return 0; }

这种方法的优势在于:

  • 线性时间复杂度:计数排序部分为O(n),插入排序部分最坏O(n²)但实际表现良好
  • 空间换时间:需要额外的存储空间来分组存储数据
  • 适合特定场景:当分数范围有限且远小于n时效率最高

5. 三种方法的对比与选择

下表总结了三种实现方式的关键特点:

特性标准库sort冒泡排序计数+插入排序
时间复杂度O(n log n)O(n²)O(n + k)
空间复杂度O(n)O(n)O(n + k)
代码复杂度
适用数据规模特定
是否需要额外空间
稳定性通常不稳定可稳定稳定

在实际竞赛中,建议优先考虑标准库sort方案,因为:

  1. 开发效率高:减少编码时间,降低出错概率
  2. 运行效率好:对于竞赛规模的数据足够高效
  3. 可读性强:便于检查和调试

手写排序算法更适合以下场景:

  • 学习算法原理时
  • 需要特殊排序规则或优化时
  • 在某些限制环境下(如不能使用STL)

计数排序+插入排序的组合则适用于数据具有特定分布特征(如分数范围有限)的情况。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 2:25:53

AI图文创作工具:从单一效率工具到生产力系统的进阶

AI图文创作工具&#xff1a;从单一效率工具到生产力系统的进阶 在数字内容创作领域&#xff0c;AI技术的介入已经从最初的“新奇尝试”转变为如今的“基础设施”。对于创作者、自媒体博主及中小企业运营人员而言&#xff0c;如何从琳琅满目的AI图文创作工具中筛选出适配自身业务…

作者头像 李华
网站建设 2026/6/9 2:21:56

STM32单片机光照检测智能调光系统Protest仿真+代码+报告+讲解视频

STM32单片机光照检测智能调光系统 本设计包含proteus仿真程序代码设计报告讲解视频 一、开发环境 仿真图&#xff1a;proteus 8.17 程序编译器&#xff1a;keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;C0136 二、主要功能 采用STM32F103系列单片机作为控制核…

作者头像 李华
网站建设 2026/6/9 2:20:54

02-Hooks完全指南——08-useTransition 与 useDeferredValue

useTransition 与 useDeferredValue 一、React 18 并发特性 1.1 什么是并发渲染&#xff1f; 并发渲染允许 React 在渲染过程中中断、暂停、恢复或放弃渲染&#xff0c;从而保持 UI 响应性。 1.2 两个核心 HookHook用途适用场景useTransition标记非紧急更新页面切换、搜索过滤u…

作者头像 李华
网站建设 2026/6/9 2:19:56

无法在Windows 10、win11上下载或被拦截

ttkefu无法在Windows 10上下载的原因主要是因为Windows Defender的实时防护功能阻止了安装。?具体来说&#xff0c;当Windows 10的杀毒和威胁防护功能开启时&#xff0c;它会阻止未经认证的软件安装&#xff0c;尤其是那些不在白名单中的应用。ttkefu在线沟通软件可能没有被识…

作者头像 李华
网站建设 2026/6/9 2:18:01

Panda3D:开源 3D 游戏引擎,Python 与 C++ 双语言支持

文章目录Panda3D&#xff1a;开源 3D 游戏引擎&#xff0c;Python 与 C 双语言支持Panda3D&#xff1a;开源 3D 游戏引擎&#xff0c;Python 与 C 双语言支持 Panda3D 是一款开源的 3D 渲染和游戏开发框架&#xff0c;支持 Python 和 C 两种编程语言&#xff0c;目前在 GitHub…

作者头像 李华