XJ4 STL 的 set 与 priority_queue
map
map 是一种映射容器,其头文件是 map。
| 功能 | 说明 |
|---|---|
map<x,y> m |
建立一个名字为 的映射,下标类型为 x,元素类型为 y。 |
m[x]=y |
将 的值设为 |
m.find(x)!=a.end() |
判断 是否存在 |
m.erase(x) |
将 删除 |
m.clear() |
清空 |
m.size() |
返回 中的元素数量 |
遍历 map 可以使用迭代器。
map<int,int> m;
for(map<int,int>::iterator i=m.begin();i!=m.end();i++){
int id=i->first; //id 为下标
int value=i->second;//value 为元素
}
其中 map<int,int>::iterator 在使用 C++11 以上时可替换为 auto,CSP-J/S 及 NOIP 等比赛可以使用。auto 为自动类型推断,请勿滥用 auto。
map 底层为二叉平衡树(红黑树),因此单次操作时间复杂度为 。
set
set 是一个 不可重 集合,其头文件是 set。
| 功能 | 说明 |
|---|---|
set<x> s |
建立一个名字为 的集合,元素类型为 x。 |
s.insert(x) |
将 插入集合 |
s.find(x)!=a.end() |
判断 是否在集合中 |
s.erase(x) |
将 从集合中删除删除 |
s.clear() |
清空 |
s.size() |
返回 中的元素数量 |
遍历 set 可以使用迭代器。
set<int> s;
for(set<int>::iterator i=s.begin();i!=s.end();i++){
int value=*i;
}
set 会自动将元素去重并进行升序排序。
map 底层为二叉平衡树,因此单次操作时间复杂度为 。
multiset
multiset 与 set 类似,但是 multiset 是 可重的,其头文件是 set。
由于 multiset 是可重的,所以做删除操作有两种情况,分别是删除所有值为 x 的元素,和删除一个值为 x 的元素。
s.erase(x) //删除所有值为 x 的元素
if(s.find(x)!=s.end()){
s.erase(s.find(x)); //删除一个值为 x 的元素
}
可以通过 lower_bound() 函数与 upper_bound() 函数查询 mutiset 中 x 的前驱及后继。
set<int>::iterator it=s.lower_bound(x);
it--;
int pre=*it; //前驱
set<int>::iterator it=s.upper_bound(x);
int nxt=*it; //后继
priority_queue
priority_queue 是一个优先队列,在头文件 queue 中。
优先队列是一个弹出元素时弹出最大值的数据结构。
priority_queue 可在 的时间复杂度插入元素,在 的时间复杂度获取/弹出队首元素。
| 功能 | 说明 |
|---|---|
priority_queue<x> q |
建立一个名字为 的优先队列,元素类型为 x,队首为最大值。 |
priority_queue<x,vector<x>,greater<x> > q |
建立一个名字为 的优先队列,元素类型为 x,队首为最小值。 |
q.top() |
获取队首元素 |
q.pop() |
获取队首元素 |
q.size() |
返回 中的元素数量 |
q.push(x) |
将元素 插入到 中 |
例题:【模板】堆
给定一个数列,初始为空,请支持下面三种操作:
- 给定一个整数 ,请将 加入到数列中。
- 输出数列中最小的数。
- 删除数列中最小的数(如果有多个数最小,只删除 个)。
思路:使用 priority_queue<int,vector<int>,greater<int> > q 让最小值放在队首,按照题目说明及上方表格完成操作。
例题:合并果子
通过模拟合并的过程,我们会发现每次选择两个最小的元素合并成较大的元素是最优策略,可以由哈夫曼编码证明(具体请参考《深基》)
因而,每次从序列中找到最小值和次小值,将其相加再放入序列中即可。时间复杂度为 。