某些STL用法

STL大法好!

stable_sort

基于归并排序,时间复杂度稳定同时并不会改变相对顺序,平替sort,用法一模一样。(可以过一些甚至卡sort的毒瘤,但是由于sort是均摊复杂度 \(O(nlogn)\),因此sort在某些题中会快一点,如SA)

bitset

按照 Oi Wiki 的说法,bitset严格上来说并不是STL,但是其应用非常的广泛,运用在各类复杂度错误但不多的题中去优化常数,一般而言可以优化32倍然后就可以卡过了

  1. 定义:bitset<1000> bs; 这里的1000指的是其位数,大概可以理解为你开了1000个bool变量,只是比存储空间及时间比bool小得多。
  2. 初始化:对于bitset的初始化与其他STL有很大不同。
    全部设为一:bitset <16> (0xFFFF),其中一个F代表4个1
    自由设置:bitset<8> b("10110101"),直接用字符串定义也很常用
    用一种bitset也可以直接去初始化另一个bitset,
std::bitset<8> original("10101010");
    
    // 使用original初始化另一个bitset
    std::bitset<8> a(original);
  1. 操作位:
b.set(); // 将所有位设置为1
b.set(loc);//将某一位改为1
b.reset(); // 将所有位设置为0
b.reset(loc);//将某一位改为0
b.flip(); // 翻转所有位的值
b.flip(loc);//翻转某一位
  1. 访问位:
    b.test(loc)会返回一个bool值。注意是从编号0开始的。
    b.count()返回一个整数(是unsigned的吗?不知道,没人说),表示这整个容器中1的值
    b.size()返回容器大小。
    b.any()是否有1
    b.none()是否全0
    b.all()是否全1
    b._Find_next(pos)寻找第pos后的第一个1.注意不包括pos位本身。如果后面没有1了,就会返回 bitset<N>::npos

同时,bitset支持各种逻辑运算,可以直接将两个bitset与、或、异或起来,相当方便。

set

set作为一种非常强大的容器,支持各种类型的操作。
set <int> st 可以定义一个set

st.emplace(x) 插入一个值x

st.find(x) 找到某个值x 所表示的迭代器

st.erase(x) 删除一个数。这里x可以是指删除某一个数值为x的数,也可以是一个迭代器表示删除这个迭代器所代表的数。
st.erase(st.find(30)),但是要注意30是否在这个set中,如果不在find会返回st.end(),会导致RE。所以一般而言前面会加一个判断
同时,erase会返回下一个有效的迭代器。
st.size() 询问大小 。st.empty() 判断是否为空。

同时,其插入后的序列是直接有序的,同时 \(\log\) 级的运算量,可以直接使用lower_bound等查找或者去重等需要有序的函数。
注意lower_bound()和upper_bound() 返回的都是迭代器。
同时set里的这两个函数有些特殊,其是特别封装了的,有:
st.lower_bound(x) 返回值x的迭代器。

与vector不一样的是,在正常的编程中,set对于迭代器的使用会更广泛,因为各种函数返回的都是迭代器,而vector一般有直接返回值的替代品。
一般而言可以通过一种偷懒的办法定义一个迭代器:
auto it=st.begin();
这时系统会知道你在定义一个迭代器。但是请保证 原set不为空。否则会运行时错误。
如果需要传统的定义一个迭代器,有:
set<int>::iterator it;
使用 *it 即可调用这个迭代器所表示的值。

通过for(const auto& val:st) 来遍历整个set。注意这里的val直接就是set里的数值,不是迭代器,不需要加上'*'号。

set 的可重版本是 multiset

map

作为映射表,其功能非常强大。map 的函数用法与 set 类似,其中对于迭代器的应用需要重点强调。
map 用法博客(偷个懒)

pair

事实上,简单的 pair 也属于STL的范畴,同时其应用很广。有些时候一些c++标准库自带的返回值就是pair类型。需要通过一些方式来快速的理解,有效的维护并使用这些返回值。

头文件:#include <utility>
定义:pair <int,bouble> p1(1,0.11);
访问值:cout<<p1.first<<' '<<p1.second;
二元关系:(按 first 项为第一关键字,second 项为第二关键字)

pair<int, int> p2(1, 2), p3(1, 3);
cout << (p2 < p3) << std::endl; // 输出 1

由于 mapunordered_map 有两个参数,因此其函数返回值很多都是 pair 类型的。
例如:std::map<int, std::string> 的每个元素是一个 std::pair<const int, std::string>
例如,定义一个 map 类型,其 .begin() 的返回值就是 pair 类型。(注意 map 中的所有元素都是有序的)

map <int,int> mp;mp[3]=2,mp[2]=2;
int u,v;tie(u,v)=*mp.begin();
cout<<u<<' '<<v<<'\n';

这里的 tie(u,v) 指的是将后面的 pair 类型的 first 项与second 项分别放到 \(u,v\) 中。
注意这里的 mp[top].begin() 返回的是一个 map 的迭代器,而 *mp[top].begin() 则是解引用后的键值对(pair 类型)
make_pair() 可以创造一个临时的 pair 类型。

string

这个也算是 STL 的一种。

需要注意的是,我们平时使用的的时候可能将其与字符数组看成类似的东西。但是如果我们要将一个没有初始化大小的字符串直接拿来使用,就有可能因为编辑器没有给其预留足够的空间导致爆掉。(也就是其不是像 vector 一样动态开空间的,如果你不预设一个大小可能编辑器就只分配给你一个极小的空间导致小数据都会越界)

posted @ 2024-11-27 10:53  all_for_god  阅读(31)  评论(0)    收藏  举报