2.set
set可以看作一个集合,可以实现自动排序(升序)和去重
在许多题目中,都可以使用这个模板库,减少很多操作,例如P1923 第k小数,当然,这道题有很多奇奇怪怪的做法,分值都不同,之后会讲解
set的定义
#include<set> //头文件
using namespace std; //这条必须加
set<typename> a; //同vector一样,这里可以用不同的数据类型
set<typename> b[SIZE]; //定义set数组,有点类似vector的二维数组
//b[0]~b[SIZE-1]都为set容器
其实很多与vector相似的地方,其他的许多STL容器感觉也都差不多。接下来是set的遍历,和vector不一样的是,这里只能用迭代器遍历,不能使用数组下标
set<typename> name;
for(set<typename>::iterator it=name.begin();it!=name.end();it++){
cout<<*it<<" ";
} //只能使用迭代器访问
然后是涉及到的一些函数(都只介绍常用的);
①insert( ) insert(x),将x放入集合中,并自动去重和升序排序,时间复杂度为O(logN),N为元素个数
②find( ) find(x)返回set中对应值为x的迭代器,时间复杂度为O(logN)
③erase( ) 时间复杂度为O(1)
用法(1)erase(x)删除对应值为x的元素;用法(2),同find( )一起使用,erase(find(x)),用find找到x的迭代器,然后删除。
④同vector一样,可以使用clear( ),时间复杂度为O(N);size( ),时间复杂度为O(1)
另外,set和map都是用红黑树来实现
例题
P1932 第k小数
(一) 非常简单暴力的思路,直接用sort快排,输出,60分,超时
(二)学了set之后,因为set自动排序,就选用了set,至于找到第k个数,可以直接用迭代器初始值为a.begin( ),然后进行k次it++。结果只有20分,是因为set要去重,导致处理之后数据出错
set<int>::iterator it = a.begin( );
while(--k)it++;
cout << *it;
(三)在查询了一些资料之后,发现有一个东西叫做multiset,和set的许多用法相同,但是他处理数据是不会进行去重的,只会升序排列。但是也只有60分,依然改变不了他超时的事实
multiset<int>::iterator it = a.begin( );
while(k--)it++;
cout << *(it);
(四)无奈之下,通过题解,发现STL还有一个叫做nth_element的东西,nth_element(a,a+k,a+n),三个参数分别指(数组名,第k个,数组长度)当时直接给我看懵了,100分做法
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
nth_element(a+1,a+k+1,a+1+n);
printf("%d",a[k+1]);
当然还可以用二分做,但这里主要是讲set,就不阐述了,通过这道题,可以加深对set的一些理解,例如做题时的选择,是否考虑去重的问题,当然还有时间复杂度