跳转至

STL

方法速览

任务 方法 口诀
最值 *min_element(a, a+n) / *max_element(...) 取星号才到值
去重 sortunique,返回尾后迭代器 + erase 先排再去
二分三件套 lower_bound(≥)、upper_bound(>)、binary_search(在不在) lower 带等号
小根堆 priority_queue<int, vector<int>, greater<int>> 默认大根,要小根写 greater
scanf 读 double 必须 %lf;printf 输出用 %f%lf 也行) 入严格出宽松

STL 函数速查

函数 用法 说明
swap(a, b) 交换两变量 内置类型、容器都可
min(a, b) / max(a, b) 取小 / 大 同类型才可比
min_element / max_element *min_element(a, a+n) 返回迭代器,加 * 取值
unique unique(v.begin(), v.end()) 只去相邻重复,先 sort
lower_bound lower_bound(a, a+n, x) - a 第一个 ≥ x 的下标
upper_bound 同上 第一个 > x 的下标
binary_search 返回 bool 只判存在,不给位置
sqrt(x) / pow(x, y) <cmath> 返回 double
log2(x) / log10(x) 自然/常用对数 换底 \(\log_a b = \log b / \log a\)
isupper / islower / isdigit 判字符类别 返回 bool
toupper / tolower 大小写转换 char(toupper(c))
strcmp strcmp(s1, s2) 0 相等、<0 / >0 比大小
memset / memcpy 按字节填 / 拷贝 memset(a, 0, sizeof a)只能填 0 / -1
fopen / fclose 文件读写 比赛用 freopen 重定向
reverse reverse(a, a+n) 原地翻转
count / find 计数 / 找位置 线性扫描

memset 陷阱:它按字节填充——memset(a, 1, sizeof a) 得到的是 0x01010101(16843009),不是 1;常用值只有 0 和 −1(全 1 字节)。

scanf/printf 格式详解

类型 scanf printf 备注
int %d %d
long long %lld %lld Windows 旧编译器曾用 %I64d,现代无碍
float %f %f
double %lf %f%lf 亦可) 输入必须 %lf
char %c %c 不跳过空白(空格回车照读)
字符串(char 数组) %s %s scanf 遇空白停

格式化控制:

写法 效果
%5d 场宽 5,右对齐 ␣␣␣42
%-5d 左对齐 42␣␣␣
%02d 补零到 2 位 07
%.2f 保留 2 位小数(四舍五入) 3.14
%05.1f 补零 + 1 位小数 007.5

%c 不跳空白是高频坑:scanf("%d", &n); scanf("%c", &c); 会把换行读进 c——中间加 getchar() 或用 %c(前置空格跳过空白)。

容器全表

容器 头文件 底层 核心操作 特点
string <string> 动态字符数组 + size() substr [] 可增长、无 \0 概念
vector <vector> 动态数组 push_back size() [] pop_back 尾部 O(1)
array <array> 定长数组 [] size() 编译期定长,带 STL 接口
pair <utility> 两个值 first second 按字典序比较
stack <stack> 适配器 push top pop LIFO
queue <queue> 适配器 push front pop FIFO
priority_queue <queue> push top pop 默认大根堆
deque <deque> 双端块 push_front/back 两端 O(1)
list <list> 双链表 push_front/back splice 不支持下标
set <set> 红黑树 insert erase count 有序去重,\(O(\log n)\)
multiset <set> 红黑树 同上 有序可重复
map <map> 红黑树 mp[key] count erase 有序键值对
unordered_set/map <unordered_...> 哈希表 同上 无序,均摊 O(1)

priority_queue 大小根

1
2
3
priority_queue<int> q;                                          // 大根堆(默认)
priority_queue<int, vector<int>, greater<int>> q;                // 小根堆
priority_queue<pair<int,int>> q2;                                // 按 first 优先

set 的 count 只返回 0/1(存在性);map 的 [] 在键不存在时会自动插入默认值——查询不想插入要用 count/find

迭代器

1
2
3
4
vector<int>::iterator it = v.begin();   // 指向第一个
                                       // v.end() 指向【最后一个的下一位置】
for (auto it = v.begin(); it != v.end(); ++it)
    cout << *it;                        // 解引用取值
  • *it 取值、it->member 访问成员(pair/结构体);
  • end()尾后位置,遍历条件写 it != v.end()
  • 迭代器失效erase 后原迭代器失效,用返回值接住:it = v.erase(it);;边遍历边删是事故高发区。

set/map 常用技巧

需求 写法
最小键 *s.begin()
最大键 *s.rbegin()
第一个 ≥ x *s.lower_bound(x)
第一个 > x *s.upper_bound(x)
元素存在? s.count(x)(set 版返回 0/1)
删除值为 x 的全部(multiset) s.erase(x);只删一个用 s.erase(s.find(x))

set<int> s = {3, 1, 4, 1, 5}(自动去重排序为 {1,3,4,5}):*s.begin() = 1*s.rbegin() = 5*s.lower_bound(3) = 3s.count(1) = 1

练习题目

练习 1 · min_element 返回值

题目

int a[] = {5, 2, 9}; 取最小值的正确写法( )

  • A. min_element(a, a+3)
  • B. min(a, a+3)
  • C. *min_element(a, a+3)
  • D. a.min()
答案与解析

答案:C

min_element 返回迭代器(指针),要加 * 解引用;A 打印出来是地址。

练习 2 · min/max 的参数

题目

max(3, 5.5) 的结果( )

  • A. \(5.5\)
  • B. \(5\)
  • C. 编译错误(类型不同)
  • D. 不确定
答案与解析

答案:C

max 要求两参数同类型;写 max(3.0, 5.5)max<double>(3, 5.5)

练习 3 · unique 的前提

题目

unique(v.begin(), v.end()) 直接去重的前提是( )

  • A. 无需任何前提
  • B. 元素都是偶数
  • C. v 是 set
  • D. 序列已排序(它只去相邻重复)
答案与解析

答案:D

unique 只把相邻重复挪到后面——标准套路是 sortuniqueerase 三连。

练习 4 · 去重三连

题目

vector 去重的完整套路是( )

  • A. sortuniqueerase(unique(...), end())
  • B. 只 unique
  • C. 只 sort
  • D. reverseunique
答案与解析

答案:A

unique 把重复挪到尾部并返回新尾后位置,erase 才真正删掉;只 sort 不去重、只 unique 不排序都会翻车。

练习 5 · lower_bound 语义

题目

lower_bound(a, a+n, x) - a 得到( )

  • A. 第一个 > x 的下标
  • B. 第一个 ≥ x 的下标
  • C. x 的下标
  • D. 最后一个 ≤ x 的下标
答案与解析

答案:B

lower 带等号;upper 才是严格大于。

练习 6 · upper_bound

题目

有序数组 \(\{1, 3, 3, 5\}\)upper_bound(a, a+4, 3) - a =( )

  • A. \(1\)
  • B. \(2\)
  • C. \(3\)
  • D. \(4\)
答案与解析

答案:C

第一个 > 3 的位置是下标 3(元素 5);顺带:lower_bound(3) = 1、两者之差 3−1 = 2 恰是 3 的个数

题目

binary_search(a, a+n, x) 返回( )

  • A. 下标
  • B. bool(存在与否)
  • C. 值
  • D. 迭代器
答案与解析

答案:B

它只回答“在不在”;要位置用 lower/upper_bound。

练习 8 · pow 的返回类型

题目

cout << pow(2, 10); 可能输出 1024 也可能输出 1023.999... 截断问题——稳妥写法( )

  • A. (int)pow(2, 10) 之前先 roundint(pow(2,10) + 0.5)
  • B. 直接 (int)pow(2,10) 一定安全
  • C. pow 只能算浮点不能用
  • D. 用 2 ^ 10
答案与解析

答案:A

pow 返回 double 有微小误差,截断可能差 1——四舍五入再转 int;D 的 ^异或不是乘方(=8)。

练习 9 · 大小写转换

题目

把字符 c 转成大写( )

  • A. (char)c.upper()
  • B. c + 26
  • C. c * 2
  • D. c - 'a' + 'A'toupper(c)
答案与解析

答案:D

ASCII 差 32:'A' - 'a' = -32;toupper 是标准库版本(非字母原样返回)。

练习 10 · strcmp

题目

strcmp("abc", "abd") 的返回值( )

  • A. \(0\)
  • B. 负数
  • C. 正数
  • D. \(1\)
答案与解析

答案:B

逐字符比较到 'c' < 'd' 返回负数——只保证符号,不保证返回 −1。

练习 11 · memset 陷阱

题目

memset(a, 1, sizeof(int) * 4)a[0] 的值是( )

  • A. \(1\)
  • B. \(16843009\)(0x01010101)
  • C. \(0\)
  • D. 未定义
答案与解析

答案:B

memset 按字节填:每字节 0x01,int 四字节拼成 0x01010101——只有 0 和 −1 整数安全

练习 12 · double 的输入格式

题目

double x; 用 scanf 读入的格式符( )

  • A. %f
  • B. %lf
  • C. %d
  • D. %c
答案与解析

答案:B

输入必须 %lf(float 才是 %f);printf 输出 double 用 %f 即可。

练习 13 · %c 的空白

题目

1
2
3
int n; char c;
scanf("%d", &n);
scanf("%c", &c);
输入 3\nA,c 得到( )

  • A. 'A'
  • B. '\n'
  • C. '3'
  • D. 空格
答案与解析

答案:B

%c 不跳过空白,换行被吃掉——改用 scanf(" %c", &c)(% 前加空格)先跳空白。

练习 14 · 补零输出

题目

printf("%02d:%02d", 7, 5); 输出( )

  • A. 7:5
  • B. 07:05
  • C. 7: 5
  • D. 7.5
答案与解析

答案:B

0 前缀补零、宽度 2——时间格式输出标准写法。

练习 15 · 两位小数

题目

printf("%.2f", 3.14159); 输出( )

  • A. 3.1
  • B. 3.142
  • C. 3.15
  • D. 3.14
答案与解析

答案:D

.2 保留两位小数(第三位四舍五入,此处 1 舍去)。

练习 16 · 场宽

题目

printf("[%5d]", 42); 输出( )

  • A. [00042]
  • B. [42␣␣␣]
  • C. [42]
  • D. [␣␣␣42]
答案与解析

答案:D

宽度 5 默认右对齐左补空格;%-5d 左对齐、%05d 补零。

练习 17 · vector 的操作

题目

vector<int> v = {1, 2}; 执行 v.push_back(3); v.pop_back(); 后 v 是( )

  • A. {1, 2, 3}
  • B. {1}
  • C. {1, 2}
  • D. {2, 3}
答案与解析

答案:C

push 尾进、pop 尾出——一进一出回到原状。

练习 18 · 默认 priority_queue

题目

priority_queue<int> q 依次 push 3、1、4 后 q.top() 是( )

  • A. \(1\)
  • B. \(3\)
  • C. \(4\)
  • D. \(3.5\)
答案与解析

答案:C

默认大根堆,top 是最大值——“默认弹大,要小写 greater”。

练习 19 · 小根堆写法

题目

定义小根堆的正确写法( )

  • A. priority_queue<int> q;
  • B. priority_queue<int, vector<int>, greater<int>> q;
  • C. priority_queue<int, less<int>> q;
  • D. queue<int> q;
答案与解析

答案:B

三参数缺一不可(中间的 vector 是底层容器);C 是大根(less 同默认)。

练习 20 · set 的有序性

题目

set<int> s; 依次 insert 3、1、2 后遍历输出( )

  • A. 不确定
  • B. 3 1 2(插入序)
  • C. 3 2 1
  • D. 1 2 3(升序)
答案与解析

答案:D

set 底层红黑树,遍历即有序;再插 1 也不重复。

练习 21 · set 判存在

题目

判断值 x 是否在 set s 中,可写( )

  • A. s.count(x)s.find(x) != s.end()
  • B. s[x]
  • C. s.at(x)
  • D. s.top()
答案与解析

答案:A

set 没有 [](那是 map 的);count 返回 0/1。

练习 22 · map 的 [] 副作用

题目

map<string,int> mp; 执行 cout << mp["apple"]; 后( )

  • A. 输出 0 且 apple 被插入
  • B. 只输出 0
  • C. 编译错误
  • D. 输出 -1
答案与解析

答案:A

[] 对不存在的键自动插入默认值(int → 0)——纯查询用 count/find 防止误插。

练习 23 · unordered 与有序

题目

unordered_setset 的核心区别( )

  • A. unordered 不能去重
  • B. unordered 哈希实现、无序、均摊 O(1);set 红黑树、有序、O(log n)
  • C. set 更快
  • D. unordered 只能存整数
答案与解析

答案:B

要“有序遍历 / 前驱后继”用 set;只要“查在不在”用 unordered 更快。

练习 24 · 取 set 最值

题目

set s 中取最小键与最大键( )

  • A. 做不到
  • B. s.min()s.max()
  • C. s.front()s.back()
  • D. *s.begin()*s.rbegin()
答案与解析

答案:D

begin 指最小、rbegin 反向指向最大;C 是 vector/deque 的接口。

练习 25 · 迭代器基础

题目

v.end() 指向( )

  • A. 最后一个元素
  • B. 第一个元素
  • C. 最后一个元素的下一位置(尾后)
  • D. 空位置 0
答案与解析

答案:C

左闭右开区间 [begin, end)——遍历条件写 it != v.end() 的原因。

练习 26 · 边遍历边删

题目

遍历 vector 删除所有偶数,正确写法( )

  • A. for (auto it = v.begin(); it != v.end(); ) if (*it % 2 == 0) it = v.erase(it); else ++it;
  • B. erase 后仍 ++it
  • C. 直接 v.erase(it) 后继续用 it
  • D. 用 for-each 循环里 erase
答案与解析

答案:A

erase 返回下一个有效迭代器,删了不 ++、没删才 ++;B/C/D 都会踩迭代器失效。

易错小结

  • min_element/max_element 返回迭代器*min/max 要求同类型;
  • unique 只去相邻重复:sort → unique → erase 三连;
  • lower_bound ≥、upper_bound >、binary_search 只判在不在;
  • memset 只能填 0 和 −1(按字节);pow 有浮点误差,转 int 先 +0.5;
  • scanf 读 double 必须 %lf%c 不跳空白(前加空格 %c);%02d 补零、%.2f 两位小数、%5d 右对齐场宽;
  • priority_queue 默认大根,小根要 greater<int> 三参数;
  • map 的 []自动插入默认值,纯查询用 count/find;
  • set/map 有序 O(log n)、unordered 无序 O(1);最小 *begin()、最大 *rbegin()
  • end() 是尾后;erase 用返回值接住迭代器,边遍历边删别 ++。