去重排序c++(绝非正解)
对于又要排序又要去重的基础题。比如
P1059 [NOIP 2006 普及组] 明明的随机数
题目描述
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了NNN个111到100010001000之间的随机整数(N≤100)(N\leq100)(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。
输入格式
输入有两行,第111行为111个正整数,表示所生成的随机数的个数NNN。
第222行有NNN个用空格隔开的正整数,为所产生的随机数。
输出格式
输出也是两行,第111行为111个正整数MMM,表示不相同的随机数的个数。
第222行为MMM个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
输入输出样例 #1
输入 #1
10 20 40 32 67 40 20 89 300 400 15输出 #1
8 15 20 32 40 67 89 300 400说明/提示
NOIP 2006 普及组 第一题
这道题不难,代码也很短,但本人写起来觉得它很烦。为啥呢?因为用sort的话去重很烦(unique太难拼了,没学过的忽略这一句),手动排序——呃,谁学了sort之后还用手动排啊。
于是就这样,这道题很烦,归根结底,原因还是在于太老掉牙了(这种题没做过十次也有八次了)于是我今天分享一个新奇的方法。
首先,众所周知,c++里有一个STL容器叫set(集合)。
以下是它的自带函数:
| 函数 | 作用 |
|---|---|
s.insert(val) | 插入元素 val;重复元素直接忽略 |
s.size() | 返回集合中元素个数(去重后的数量) |
s.empty() | 集合为空返回 true,否则 false |
s.clear() | 清空所有元素 |
s.find(val) | 查找 val,返回迭代器;找到→指向该元素;找不到→s.end() |
s.erase(val) | 删除值为 val 的所有元素 |
s.erase(迭代器) | 删除迭代器指向的单个元素 |
s.begin() | 迭代器,指向最小元素(第一个) |
s.end() | 尾后迭代器,不指向有效元素,遍历终止条件 |
核心特性
自动有序:
容器内部使用红黑树(平衡二叉搜索树)存储元素,默认从小到大升序排列
元素唯一(自动去重):
不能存
放重复值;
插入相同元素不会报错,但是插入无效
不支持随机访问:
不能用 s[0]、s[1] 下标取值,只能依靠迭代器遍历
迭代器双向遍历,只能 ++it、–it
简单来说就是这个东西可以自动排序去重,简直就是专门为这道题设计的。所以我们要做的就是: 输入 -> 输出。
即
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;cin>>n;set<int>s;for(inti=1;i<=n;++i){intx;cin>>x;s.insert(x);}cout<<s.size()<<endl;for(autoit=s.begin();it!=s.end();++it)cout<<*it<<" ";cout<<endl;return0;}for (auto it = s.begin(); it != s.end(); ++it)这个是用迭代器遍历,没学过的就把这一句背下来并知道set只能用这个遍历就行了。(本文不负责讲解迭代器,若想详细学习,见《C++ STL迭代器完全指南:从原理到实战》)
所以我们用这段代码就能过这道题。是不是挺简便的。
本文到这里就差不多要结束了,多谢浏览。