STL——set的应用
STL是个好东西,让我来给大家分享一下STL里的集合。
首先讲讲集合的用处,集合和优先队列有点相似,往集合中插入一个数,或者将集合中的每个数删除它会自动将元素整理有序,还可以调二分查找,所有的操作都是 log 级别的
头文件
#include <set>
新建集合
STL有两种集合,一种是去重的集合,即一个元素最多只出现一次,另一种是不去重的集合,一个元素可以有多个出现。
去重的集合
set <int> S; // 定义一个int类型去重的集合
set <DATA> S; // 定义一个DATA类型去重的集合。
其中 DATA 是自定义结构体名
S.insert(x); // 向集合中插入元素 x
S.count(x); // 查看 x 是否是集合中的元素
S.erase(x); // 将集合中与 x 相等的删除
S.size(); // 返回集合的元素个数
遍历集合中的元素
set <int> :: iterator p;
for (p = S.begin(); p != S.end(); p++) //遍历
printf("%d\n", *p); //这是 *p 不是 p 哦
允许有重复元素的集合
multiset <int> S; // 定义一个int类型不去重的集合
multiset <DATA> S; // 定义一个DATA类型不去重的集合
其中 DATA 是自定义结构体名
S.insert(x); // 向集合中插入元素 x
S.count(x); // 集合中有多少个与 x 相等的元素
S.erase(x); // 将集合中所有与 x 相等的删除
S.size(); // 返回集合的元素个数
若 x 是个指针 S.erase(x) 表示将集合中 x 所指的位置删除
遍历集合中的元素
(同去重集合)
【应用】
由于集合具有排序和高效的插入和查找功能,所以经常用到
接水问题
【题目描述】
学校里有一个水房,水房里一共装有m 个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1。
现在有 n 名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从1到n 编号,i 号同学的接水量为wi。接水开始时,1 到m 号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学j 完成其接水量要求wj 后,下一名排队等候接水的同学k马上接替j 同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j 同学第x 秒结束时完成接水,则k 同学第x+1 秒立刻开始接水。若当前接水人数n’不足m,则只有n’个龙头供水,其它m-n’个龙头关闭。
现在给出n 名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。
【输入格式】
第1 行2 个整数n 和m,用一个空格隔开,分别表示接水人数和龙头个数。
第2 行n 个整数w1、w2、……、wn,每两个整数之间用一个空格隔开,wi 表示i 号同学的接水量。
【输出格式】
输出只有一行,1 个整数,表示接水所需的总时间。
【输入样例1】
5 3
4 4 1 2 1
【输出样例1】
4
这题其实是用堆,不过调用集合是可以滴。
【代码】
#include<cstdio>
#include<set>
using namespace std;
multiset <int> s;
multiset <int> :: iterator p;
int n,m,x,ans;
inline int read(){
int ret=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret;
}
int main(){
n=read(),m=read();
for (int i=1;i<=m;i++) s.insert(read());
for (int i=m+1;i<=n;i++){
p=s.begin();
x=*p;s.erase(p);
s.insert(x+read());
}
for (p=s.begin();p!=s.end();p++) ans=max(ans,*p);
printf("%d\n",ans);
return 0;
}
注意:集合的常数很大,在80000左右一般是可以的,大了就要注意超时,So,能够手写堆或者其他的什么东西就尽量手写,迫不得已比如要 logn 的删除元素或者数据比较小等等再考虑集合
尽管集合有点慢,但是集合其实还是很方便的,有些代码手码要打很久调一下集合也没有什么不可以的。
总之:STL是个好东西,STL里的set也是好东西
BY:xay5421
Date:2017.08.11