c++98~c++17 的一些好用的用法--zhengjun
c++98
find(bg,ed,val)
返回指向第一个等于 \(val\) 的元素的指针。
时间复杂度 \(O(n)\)。
fill(bg,ed,val)
将 \([bg,ed)\) 之间的所有元素赋值为 \(val\)。
复杂度为 \(O(n)\),常数略大于 memset
。
copy(bg1,ed1,bg2)
将 \([bg_1,ed_1)\) 中的元素复制到 \(bg_2\)。
复杂度 \(O(n)\)。
max_element/min_element(bg,ed)
返回指向 \([bg,ed)\) 中最大 / 最小的元素的指针。
时间复杂度 \(O(n)\)。
第三个参数可传入比较函数。
求数组最大值就可以直接写:*max_element(a+1,a+n+1)
merge(bg1,ed1,bg2,ed2,bg3)
\([bg_1,ed_1)\) 和 \([bg_2,ed_2)\) 是两个有序序列,对其进行归并并存入 \(bg_3\)。
不能够原地归并,若要原地归并请使用 inplace_merge
。
时间复杂度 \(O(ed_1-bg_1+ed_2-bg_2)\)。
可以传入第六参数作为比较函数。
inplace_merge(bg,md,ed)
将 \([bg,md)\) 和 \([md,ed)\) 归并排序,并存入 $$bg$。
时间复杂度 \(O(n)\),需要 \(O(n)\) 的额外空间。
当空间不足时使用 \(O(n\log n)\) 的原地排序。
常数较小,可能比手写的还快。
可以传入第四个参数作为比较函数。
常用于 CDQ 分治等分治算法,非常好用。
__lg(x)
返回 \(\lfloor \log_2x\rfloor\)。
时间复杂度 \(O(1)\)。
常用于实现倍增、二进制运算等。
__gcd(x,y)
返回 \(\gcd(x,y)\)。
复杂度是对数级别的,常数较小。
注意,返回值的符号 不一定 是正。
在 C++17 之前都是很常用的。
accumulate(bg,ed,val)
将 \([bg,ed)\) 中的所有所有元素与初始值 \(val\) 相加,返回这个和。
时间复杂度 \(O(n)\)。
可以传入第四个参数作为加法。
可以用于求序列和,但注意,该函数返回值与 \(val\) 类型一致,意味着你要注意 long long
的问题:
accumulate(bg,ed,0);//返回值是 int,可能溢出
accumulate(bg,ed,0ll);//返回值是 long long
partial_sum(bg1,ed1,bg2)
对 \([bg_1,ed_1)\) 做前缀和并存入 \([bg_2,bg_2+ed_1-bg_1)\)。
时间复杂度 \(O(n)\)。
可以传入第四个参数作为加法。
可以原地求前缀和。
adjacent_difference(bg1,ed1,bg2)
对 \([bg_1,ed_1)\) 求差分并存入 \([bg_2,bg_2+ed_1-bg_1)\)。
时间复杂度 \(O(n)\)。
可以传入第四个参数作为减法。
可以原地差分。
__builtin 家族
这里的内容并不在 C++ 标准中,全部都是 GNU 的私货,若使用其它编译器则可能无法通过编译。
如果 \(x\) 的类型是 long long,请务必使用 __builtin_xxxll(x)
(如 __builtin_popcountll(x)
),否则将可能造成 FST 等严重后果。
__builtin_popcount(x)
返回 \(x\) 在二进制下 \(1\) 的个数。
时间复杂度有说 \(O(\log\log x)\) 的,也有说 \(O(1)\) 的。
一定比手写的快。
__builtin_parity(x)
返回 \(x\) 在二进制下 \(1\) 个数的奇偶性。
时间复杂度 \(O(1)\),快于 __builtin_popcount(x)&1
。
__builtin_ffs(x)
返回二进制下最后一个 \(1\) 是从后往前第几位。
时间复杂度 \(O(1)\)。
__builtin_ctz(x)
返回二进制下后导零的个数,\(x=0\) 时 UB。
时间复杂度 \(O(1)\)。
__builtin_clz(x)
返回二进制下前导零的个数,\(x=0\) 时UB。
时间复杂度 \(O(1)\)。
shrink_to_fit
vector/deque/string/basic_string
的 shrink_to_fit
可以使其 \(capacity\) 调整为 \(size\) 的大小,如:
max(l)/min(l)
l
是一个初始化列表,这个函数返回 l
中最大 / 最小的元素。
时间复杂度 \(O(size_l)\)。
在多个元素求最大 / 最小时非常好用:max({a,b,c})
iota(bg,ed,val)
将 \([bg,ed)\) 中的元素依次赋值为 \(val,val+1,val+2,\cdots\)
时间复杂度 \(O(n)\)。
常用于给并查集初始化。
prev(it)/next(it)
返回迭代器 \(it\) 的前驱 / 后继。
复杂度与 ++/--
的复杂度相同,取决于容器。
begin(container)/end(container)
返回容器 \(\texttt{container}\) 的 begin()
和 end()
。
复杂度取决于容器。
作用就是相比原先要短一个字节。
mt19937 gen(chrono::system_clock::now().time_since_epoch().count());
hypot(x,y)
返回 \(\sqrt{x^2+y^2}\)。
常用于求两点之间的距离,非常方便。
set/map 的 merge
将一个 set/map 并入另一个,若将 \(t\) 并入 \(s\) ,则所有 \(t\) 中未在 \(s\) 里出现的元素将被插入 \(s\),并在 \(t\) 中被删除。
对于 s.merge(t)
,复杂度为 \(O(|t|\log(|s|+|t|))\)。
gcd(x,y)/lcm(x,y)
返回 \(\gcd(|x|,|y|)\) / \(\operatorname {lcm}(|x|,|y|)\) 的值。
复杂度对数级别的。
保证了返回值的符号是正。
\(lcm\) 的实现是先除后乘。
size(container)/empty(container)
返回一个容器的 size()
/ 是否为空。
复杂度取决于容器。
hypot(x,y,z)
返回 \(\sqrt{x^2+y^2+z^2}\)。
复杂度 \(O(1)\)。
常用来求三维中两点距离。