7.2 KiB
7.2 KiB
STL 在考场(OI/ACM)中的要点总结
在算法竞赛考场上,STL 是 C++ 的核心优势,能大幅节省时间、减少手写数据结构的错误。重点掌握常用容器和算法的操作、时间复杂度,以及常见坑。以下是针对考场的精炼总结,优先列出最常用的部分,并详细说明函数及其使用方法(包括示例代码)。
1. 常用容器(优先掌握 vector、string、priority_queue、set、map)
| 容器 | 头文件 | 特点与时间复杂度 | 考场用途 |
|---|---|---|---|
| vector | <vector> |
动态数组,支持随机访问 | 代替数组,最常用 |
| string | <string> |
动态字符串 | 字符串处理 |
| priority_queue | <queue> |
优先队列(默认大根堆) | Dijkstra、贪心选最大/小 |
| set | <set> |
有序集合(不重复,红黑树) | 自动排序、去重、二分 |
| map | <map> |
有序键值对(红黑树) | 映射、计数 |
| queue | <queue> |
普通队列(FIFO) | BFS |
| stack | <stack> |
栈(LIFO) | DFS、括号匹配 |
| deque | <deque> |
双端队列 | 滑动窗口等 |
vector 详细函数与使用
#include <vector>
vector<int> v; // 定义
v.push_back(x); // 末尾插入 O(1) amortized
v.pop_back(); // 末尾删除 O(1)
v.size(); // 元素个数
v.empty(); // 是否为空
v.clear(); // 清空
v.front(); v.back(); // 首/尾元素
v[i]; // 随机访问 O(1)
v.insert(it, x); // 迭代器位置插入 O(n)
v.erase(it); // 删除迭代器位置 O(n)
sort(v.begin(), v.end()); // 排序(常配合使用)
v.resize(n); // 调整大小
考场技巧:预分配空间 vector<int> v(n); 或 v.reserve(n); 避免多次扩容。
string 详细函数与使用
#include <string>
string s = "abc";
s += "def"; // 拼接
s.push_back('x'); // 末尾加字符
s.size() / s.length(); // 长度
s.substr(pos, len); // 子串,从pos开始len长
s.find(str); // 查找子串,返回位置(未找到string::npos)
s.erase(pos, len); // 删除子串
s.insert(pos, str); // 插入
s.clear();
char c = s[i]; // 访问
考场常用:字符串反转 reverse(s.begin(), s.end());
priority_queue 详细函数与使用(考场最常用之一)
#include <queue>
priority_queue<int> pq; // 大根堆(默认,最大值在顶)
priority_queue<int, vector<int>, greater<int>> pq; // 小根堆(最小值在顶)
pq.push(x); // 插入 O(log n)
pq.pop(); // 删除顶 O(log n)
pq.top(); // 访问顶
pq.empty(); pq.size();
// 自定义结构体(pair 或 struct)
priority_queue<pair<int,int>> pq; // 默认第一大,第二大
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq; // 小根
// 自定义比较(复杂结构体)
struct Node {
int val, id;
};
struct cmp {
bool operator()(const Node& a, const Node& b) {
return a.val < b.val; // 大根堆(改>为小根)
}
};
priority_queue<Node, vector<Node>, cmp> pq;
考场坑:小根堆写 greater<int> > 时中间加空格,避免 >> 编译错误。
set 详细函数与使用
#include <set>
set<int> st; // 有序不重复
multiset<int> mst; // 允许重复
st.insert(x); // 插入 O(log n)
st.erase(x); // 删除值 O(log n)(或 st.erase(it);)
st.find(x); // 查找,返回迭代器(未找到 st.end())
st.count(x); // 计数(set为0/1)
st.lower_bound(x); // >= x 的最小迭代器
st.upper_bound(x); // > x 的最小迭代器
st.begin(); st.end(); // 迭代器
考场技巧:去重 sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end());
map 详细函数与使用
#include <map>
map<int, int> mp; // key有序
unordered_map<int, int> ump; // 无序(C++11,平均O(1),但最坏O(n))
mp[key] = val; // 插入/修改(不存在自动插入)
mp.insert({key, val});
mp.erase(key);
mp.find(key); // 未找到 mp.end()
mp.count(key);
mp.lower_bound(key); // >= key
考场常用:计数、离散化。
2. 常用算法(头文件 <algorithm>)
| 函数 | 用法示例 | 说明与复杂度 |
|---|---|---|
| sort | sort(v.begin(), v.end()); |
O(n log n),自定义 sort(v.begin(), v.end(), cmp); |
| reverse | reverse(v.begin(), v.end()); |
反转 O(n) |
| max_element / min_element | *max_element(v.begin(), v.end()); |
返回迭代器 O(n) |
| lower_bound | lower_bound(v.begin(), v.end(), x); |
二分 >= x,O(log n)(需有序) |
| upper_bound | upper_bound(v.begin(), v.end(), x); |
二分 > x |
| unique | v.erase(unique(v.begin(), v.end()), v.end()); |
去重(需先sort) |
| next_permutation | do { ... } while(next_permutation(v.begin(), v.end())); |
全排列 |
| fill | fill(v.begin(), v.end(), val); |
填充 |
考场技巧:二分常用 lower_bound,返回迭代器减 begin() 得位置。
3. 考场通用要点与坑
- 头文件:常用
#include <bits/stdc++.h>(万能头,竞赛专用)。 - 命名空间:
using namespace std; - 迭代器:auto 遍历
for(auto &x : v) x=...;(可修改)。 - pair:
pair<int,int> p = {a,b};或make_pair(a,b);常用于 priority_queue。 - 时间复杂度:set/map O(log n),vector O(1) 访问,注意 n<=1e5~1e7 时别用 O(n^2)。
- 输入加速:
ios::sync_with_stdio(false); cin.tie(0); - 常见错误:忘清空容器、迭代器失效、优先队列比较写错、>> 空格问题、爆 int 用 long long。
这些是考场 90% 场景够用的核心。熟练后,能让你少写数百行手写代码。建议多刷题记忆模板,考前复习此表即可!如果有特定容器需要更深示例,随时问。