记录38
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[2000010]={},n,cnt;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
cnt=1;
while(a[i]==a[++i]&&i<=n) cnt++;
i--;
cout<<cnt<<endl;
}
return 0;
}
突破点
统计这些自然数各自出现的次数
👉统计数字
并按照自然数从小到大的顺序输出统计结果
👉排序
思路
- 用数组存数字
- 用sort进行排序
- 统计连续出现的数字
代码简析
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[2000010]={},n,cnt;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
...
return 0;
}
sort()对数组进行排序,关于sort排序,在文章的补充部分进行详细介绍
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[2000010]={},n,cnt;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
cnt=1;
while(a[i]==a[++i]&&i<=n) cnt++;
i--;
cout<<cnt<<endl;
}
return 0;
}
cout<<a[i]<<" "; 先输出数字
cnt=1; 第一个数为1个
while(a[i]==a[++i]&&i<=n) cnt++; 后一个等于前一个,++i跳出while循环,cnt进行计数
i--; 数不连续时跳出循环,然后退回上一个重新计数(for循环会重新加一次)
补充
sort()函数完整用法指南
1. 基本语法与头文件
#include <algorithm> // 必须包含 // 对数组排序 int arr[] = {3, 1, 4, 1, 5, 9}; sort(arr, arr + 6); // 排序整个数组 // 对vector排序 vector<int> v = {3, 1, 4, 1, 5, 9}; sort(v.begin(), v.end()); // 排序整个vector核心规则:
sort(begin, end)对左闭右开区间[begin, end)排序。
2. 排序范围控制
int arr[] = {3, 1, 4, 1, 5, 9}; sort(arr, arr + 3); // 只排序前3个元素 → {1, 3, 4, 1, 5, 9} sort(arr + 2, arr + 5); // 排序第2到第4个 → {3, 1, 1, 4, 5, 9}竞赛技巧:
sort(arr, arr + n)是排序前n个元素的标准写法。
3. 默认排序顺序
默认升序:从小到大排序
内置类型:
int,double,char,string等直接支持int a[] = {5, 2, 8}; sort(a, a + 3); // 结果:{2, 5, 8} string s = "bacd"; sort(s.begin(), s.end()); // 结果:"abcd"
4. 降序排序(三种方法)
方法A:使用
greater<>()#include <functional> int arr[] = {3, 1, 4}; sort(arr, arr + 3, greater<int>()); // 结果:{4, 3, 1}方法B:自定义比较函数
bool cmp(int a, int b) { return a > b; // 降序 } sort(arr, arr + 3, cmp); // 结果:{4, 3, 1}方法C:Lambda表达式(C++11推荐)
sort(arr, arr + 3, [](int a, int b) { return a > b; });
5. 结构体排序(竞赛核心)
方法A:重载
<运算符(最常用)struct Student { int id, score; // 按分数降序,分数相同按id升序 bool operator < (const Student& other) const { if (score != other.score) return score > other.score; return id < other.id; } }; vector<Student> students; sort(students.begin(), students.end()); // 自动调用operator<方法B:自定义比较器
bool cmp(const Student& a, const Student& b) { if (a.score != b.score) return a.score > b.score; return a.id < b.id; } sort(students.begin(), students.end(), cmp);方法C:Lambda表达式
sort(students.begin(), students.end(), [](const Student& a, const Student& b) { if (a.score != b.score) return a.score > b.score; return a.id < b.id; });
6. 稳定排序
stable_sort()当需要保持相等元素的原始顺序时使用:
struct Node { int val, idx; }; vector<Node> v = {{5,0}, {3,1}, {5,2}}; // 按val排序,val相同时保持idx小的在前 stable_sort(v.begin(), v.end(), [](const Node& a, const Node& b) { return a.val < b.val; }); // 结果:{{3,1}, {5,0}, {5,2}}(稳定)性能:时间复杂度 O(n log n),但比
sort慢,内存占用更多。
7. 部分排序
partial_sort()当只需前k个有序时使用,比全排序更快:
vector<int> v = {9, 2, 7, 4, 1, 8, 3}; // 只排序前3个最小元素到前面 partial_sort(v.begin(), v.begin() + 3, v.end()); // 结果:v = {1, 2, 3, 9, 7, 8, 4}(前3有序,其余未排序)
8. 性能分析
时间复杂度:平均 O(n log n),最坏 O(n log n)
空间复杂度:O(log n) 递归栈空间(内省排序)
稳定性:
sort是不稳定排序(相同元素可能改变顺序)
9. 常见错误与陷阱
错误1:比较器不满足严格弱序
// ❌ 错误:缺少等值处理 bool cmp(int a, int b) { return a <= b; } // 导致段错误 // ✅ 正确 bool cmp(int a, int b) { return a < b; }错误2:比较器依赖外部可变状态
int flag = 1; bool cmp(int a, int b) { return flag ? a > b : a < b; // ❌ 运行时修改flag会导致UB }错误3:对list排序
list<int> lst; sort(lst.begin(), lst.end()); // ❌ list不支持随机访问迭代器 // ✅ 正确 lst.sort(); // list自带成员函数sort
10. 竞赛最佳实践
万能模板:
// 结构体排序模板 struct Node { int x, y, id; bool operator < (const Node& other) const { if (x != other.x) return x < other.x; // 第一关键字升序 if (y != other.y) return y > other.y; // 第二关键字降序 return id < other.id; // 第三关键字升序 } }; // Lambda排序模板(更灵活) sort(v.begin(), v.end(), [](const Node& a, const Node& b) { return a.x < b.x; });性能优化:
小规模数据(n < 1000):
sort和stable_sort差异不大大规模数据(n > 10^5):优先
sort,避免stable_sort部分有序:
sort仍然高效,但partial_sort更快(只需前k个时)可读性建议:简单逻辑用重载运算符,复杂逻辑用Lambda,避免单独定义比较函数。
核心要点总结
区间左闭右开:
sort(begin, end)不包含end默认升序:内置类型无需比较器
降序三选一:
greater<>, 自定义函数, Lambda结构体必重载:
operator <是竞赛最速写法稳定性需求:用
stable_sort性能保证:O(n log n) 适合所有竞赛场景
严格弱序:比较器必须满足
a<b和b<a不能同时成立掌握以上用法,可覆盖CSP竞赛中所有排序需求。
946

被折叠的 条评论
为什么被折叠?



