一些标准库和语法的内容。
主要参考cppreference.com。
输入输出
如果你是c党,想要读入一行,可以使用fgets(char *str,int count,FILE *stream)
这个函数,看起来用法可能是fgets(s,inf,stdin)
这样的。
不过更好的方法是使用scanf("%[^\n]",s)
这样的。来详细学习一下scanf()
。
scanf()
的第一个参数称为格式字符串,它用来匹配输入的串。格式串中每个需要被输入的东西用一个%...
这样的表示,比如我们经常会用到%d %f %c %s
这样的。不需要被输入的东西会被匹配之后扔掉,比如我写scnaf("qwq%dqwq",&x)
,输入qwq114514qwq,得到x是114514。如果你想要扔掉%这个字符,使用%%
。如果你写了一个空白字符,那么scanf()
会匹配极长连续空白字符,如果你写了两个也是一样的。写空格,换行和tab是没有区别的。
%后面跟的东西有很多种,这称为转换规范。按写的顺序给出一般情况下可能用到的 :
-
赋值抑制字符
*
,表示不会把这个结果赋值给任何参数。 -
一个数表示最大读取长度。对于会跳过空白字符的转换格式说明符,它不计算这些空白字符。
-
表示参数类型的长度修饰符,比如
ll
,L
这样的。 -
转换格式说明符。
-
d
匹配十进制整数,u
匹配无符号十进制整数,o
匹配八进制整数,x
匹配十六进制整数。可以被hh
(char, 1 byte),h
(short, 2 bytes),l
(long, 4 bytes),ll
(long long, 8 bytes)修饰。所以cf的I64
是什么鬼东西? -
f
匹配一个浮点数,可以被l
(double, 8 bytes),L
(long double, 12 bytes)修饰。 -
s
匹配一个不包含空白字符的字符串。 -
[S]
匹配集合S中的字符组成的字符串,这个集合可以包含空白字符。集合类似于正则的写法,也就是把一堆摞起来,在一开始可以加一个^
表示补集。但是不一定可以使用a-z
这样的表示,不过我感觉主流编译器应该都可以,不过还是不要轻易在正式比赛中尝试。 -
c
一般被用来匹配一个字符,请注意这个字符可以是空白字符。请注意它不会在读入的最后写一个\0
进去。看起来可以被[S]
代替。
-
请注意使用%s和%[S]读取字符串的时候,最后必须留一位,因为scanf总是会在串后面放一个空字符。我一般读串会留十位(
printf()是类似的。特别地,%后面依次可以选择使用这些符号
-
负号
-
表示在域中左对齐。关于域是什么,就是这个%…所输出的那一段。 -
加号
+
表示对于有符号数,始终输出它的符号,而不是在它是负数的时候才输出。 -
空格
-
井号
#
表示对于八进制输出前导0,十六进制输出0x,浮点数总是输出小数点,除此之外是ub。好像没什么用。 -
0
表示对于整数和浮点数,用前导零代替空格来填充域。 -
一个数或者星号
*
指示最小域宽,也就是输出的最小长度,如果不满默认用空格填充在前面,可以被负号或者0改变。使用星号表示用一个额外参数指示。 -
点
.
后面一个整数或星号*
表示精度,对于整数这个是长度。使用星号表示用一个额外参数指示。 -
表示参数类型的长度修饰符。
-
转换格式说明符。与
scanf()
相比,多了e表示科学计数法,a表示十六进制浮点数。
sscanf()
和sprintf()
可以把东西从一个char*
里面读出来或者写进去。fscanf()
和fprintf()
可以读文件指针,比较常见的是用来输出调试语句,使用fprintf(stderr,"Debug: %d",x)
这样的。
算法库
c是有排序算法的/jy,但是好像没有复杂度保证。它叫qsort()
,在<stdlib.h>
中。
inplace_merge()
实现了归并排序一层的过程,而stable_partation()
实现了快速排序一层的过程,不过看起来后者没有啥用,因为我们有nth_element()
。
数值库
valarray<T>
来自<valarray>
,实现了一个类型T的定长数组,可以方便地实现点对点的操作。当然很多时候会选择手写这种。
isinf()
,isnan()
和isfinite()
来自<math.h>
,可以检查一个数是不是inf,是不是nan,是不是inf和nan之外的数。
我平时使用xorshift生成随机数。如果要塞进shuffle()
里面,可以用mt19937 r(random_device{}())
这样的。
容器库
vector.reserve()
用来申请空间。vector.clear()
不会释放空间,如果要释放空间地clear,可以使用vector<>().swap(v)
这样的;如果要缩小空间,可以使用vector.shrink_to_fit()
。
使用vector.data()
可以得到vector底层的数组。
pbds
可以这样定义顺序统计树 :
1
2
3
4
5
6
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
然后用ordered_set.find_by_order()
查询kth,ordered_set.order_of_key()
查询rank。
rope不是很好用。pbds的堆用于优化dij必然完全没有我的基数堆快,可并堆的话左偏树/配对堆也不难写。hash table容易手写。只有平衡树难写了!我去,是不是写一万个平衡树题就可以抛弃pbds了(
lambda表达式
[捕获](参数)修饰符{函数体}
。捕获是以逗号分隔的列表,用于使用lambda表达式声明处的局部变量,每一项可以是&a =a this
这样的,&a
表示可以使用局部变量a
的引用,=a
表示使用copy,如果只写& =
不写a
则表示对所有变量。this
表示可以使用所在类的成员。如果留空则表示不捕获任何变量。参数就是参数。修饰符有multable
,表示如果以copy捕获了一个变量,可以修改它的值(而对外面没有影响)。