c++常用自带函数用法与注意

一、头文件与基础

复制代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int,int>;

二、<algorithm> 算法全家桶(最常用)

1. sort ------ 排序

复制代码
sort(a.begin(), a.end());                    // 默认升序
sort(a.begin(), a.end(), greater<int>());    // 降序
// 自定义比较(lambda)
sort(v.begin(), v.end(), [](auto &x, auto &y) {
    return x.val < y.val;   // 小的在前
});

注意

  • sort 不稳定,相等元素相对顺序可能变
  • 需要稳定用 stable_sort
  • 结构体排序重载 < 也可以,但 lambda 更灵活

2. min / max / clamp

复制代码
int x = min(a, b), y = max(a, b);
int z = clamp(val, 0, 100);   // C++17,val 限制在 [0,100]

不要 min(a++, b++),有未定义行为;用 min({a,b,c}) 三值比较要 C++11。


3. swap

复制代码
swap(a, b);

自定义类型要有可移动/可拷贝,STL 容器 O(1) swap。


4. reverse / rotate

复制代码
reverse(a.begin(), a.end());                 // 翻转
rotate(a.begin(), a.begin() + k, a.end());   // [0,k) 移到末尾(左移 k)
// 右移 k:rotate(a.begin(), a.end()-k, a.end());

5. unique + erase(去重)

复制代码
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());   // 经典离散化前处理

unique 不去重,只是把不重复元素移到前面,返回新尾迭代器


6. lower_bound / upper_bound(二分神器)

复制代码
auto it = lower_bound(v.begin(), v.end(), x); // 第一个 >= x
auto it = upper_bound(v.begin(), v.end(), x); // 第一个 > x
int pos = lower_bound(v.begin(), v.end(), x) - v.begin();
函数 语义
lower_bound ≥ x
upper_bound > x
binary_search 存在性 bool

必须有序,自定义比较时两个参数要一致:

复制代码
lower_bound(v.begin(), v.end(), x, [](const Node& a, int b) { return a.val < b; });

三、数学函数

gcd / lcm(C++17)

复制代码
int g = gcd(a, b);       // 负数自动取 abs
int l = lcm(a, b);       // 小心溢出

ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }

abs / labs / llabs

复制代码
ll x = llabs(-1000000000000LL);   // int abs 对 ll 会截断!

pow / sqrt

复制代码
ll x = sqrt(n);   // 浮点误差!整数开根要
ll x = (ll)sqrt(n); while(x*x>n)x--; while((x+1)*(x+1)<=n)x++;

永远不要对整数用 pow 做精确计算pow(10,3) 可能是 999


四、容器全家桶

vector

复制代码
vector<int> v(n, 0);    // n 个 0
v.push_back(x);
v.pop_back();
v.resize(n);            // 改大小,多的截断,少补默认
v.reserve(n);           // 只扩容量不初始化,不增加 size
v.emplace_back(x);      // 比 push_back 少一次拷贝,快一丢丢

遍历中不能 push_back 然后依赖索引不失效 ,但迭代器会失效;resize 前访问越界直接 RE。


deque(双端队列)

复制代码
deque<int> dq;
dq.push_back(x); dq.push_front(x);
dq.pop_front(); dq.pop_back();

滑动窗口队头队尾操作、单调队列常用

比 vector 慢,随机访问略慢,内存不连续


stack / queue / priority_queue

复制代码
stack<int> st;  st.push(x); st.top(); st.pop();
queue<int> q;   q.push(x);  q.front(); q.pop();

优先队列(大根堆默认)

复制代码
priority_queue<int> pq;                      // 大根堆
priority_queue<int, vector<int>, greater<int>> minpq;  // 小根堆
pq.push(x); pq.top(); pq.pop();

priority_queue 没有 clear() 方法 !想清空只能 pq = priority_queue<int>();

结构体小根堆写法

复制代码
struct Node { ll d; int u; };
priority_queue<Node, vector<Node>, function<bool(Node,Node)>> pq(
    [](Node a, Node b) { return a.d > b.d; }   // 注意:STL 里比较是"大于"表示小根
);
// 或者重载 operator< 时反过来写

set / multiset / map / multimap

复制代码
set<int> s;
s.insert(x); s.erase(x);        // 按值删所有(set 里只有一个)
s.erase(s.find(x));             // 按迭代器删 O(1) 不检查存在
if (s.count(x)) ...
auto it = s.lower_bound(x);     // 第一个 >= x

找前驱/后继

复制代码
auto it = s.lower_bound(x);
if (it != s.begin()) it--;      // 前驱
auto nxt = s.upper_bound(x);    // 后继

erase(key) 返回删除个数,set 是 O(log n);erase(iterator) 是 O(1) amortized

multiset 删一个元素

复制代码
auto it = ms.find(x);
if (it != ms.end()) ms.erase(it);   // 只删一个
ms.erase(x);                         // 全删光!

unordered_map / unordered_set

复制代码
unordered_map<string, int> mp;
mp["abc"] = 1;
if (mp.count("abc")) ...

期望 O(1)

注意:

  • 最坏 O(n)(卡哈希,CF 有专门卡数据)
  • 自定义 struct 要写 hash 函数
  • 不能存指针/迭代器依赖顺序

能用 map 就别用 unordered_map,除非 n 很大且不怕被卡


bitset(位运算神器)

复制代码
bitset<1005> a, b;
a.set(); a.reset(); a.flip();
a[i] = 1;
cout << (a & b).count();     // 1 的个数
cout << a.to_string();

状态压缩 DP、BFS 判重、Floyd 传递闭包

大小必须是编译期常量 ,不能 bitset<n> 变量


array(C++11 定长数组)

复制代码
array<int, 1005> a;
sort(a.begin(), a.end());   // 比 int a[1005] 多了 STL 接口

五、字符串

复制代码
string s;
s.substr(pos, len);          // len 超了就截到末尾
s.resize(n, '0');
s.find("abc");              // 找不到返回 string::npos
s += 'x'; s += t;           // O(1) amortized

字符串转数字 / 数字转字符串

复制代码
int x = stoi(s); ll x = stoll(s);
double d = stod(s);
string t = to_string(x);

字符串流(读空格分隔)

复制代码
stringstream ss(line);
while (ss >> x) ...

substr 频繁用会拷贝,大数据量用 string_view(C++17)或索引


六、pair / tuple / tie

复制代码
pii p = {1, 2};
auto [x, y] = p;        // C++17 结构化绑定

tuple<int,int,ll> t(1,2,3LL);
get<0>(t);

tie(x, y) = minmax(a, b);   // 同时拿最小和最大

pair 自动按 first 再 second 字典序比较,排序神器


七、Lambda & 函数对象

复制代码
auto cmp = [&](int i, int j) { return dist[i] < dist[j]; };
sort(v.begin(), v.end(), cmp);

// 递归 lambda(要捕获自身)
function<void(int)> dfs = [&](int u) {
    for (int v : G[u]) dfs(v);
};

递归 lambda 必须用 function<> 包裹,否则捕获不到自己


八、二分模板(手写,不踩坑)

复制代码
// 找第一个满足 check 的位置 [L,R]
int l = L, r = R, ans = -1;
while (l <= r) {
    int mid = l + (r - l) / 2;
    if (check(mid)) ans = mid, r = mid - 1;
    else l = mid + 1;
}

// 浮点二分
double l = 0, r = 1e9;
while (r - l > 1e-9) {
    double mid = (l + r) / 2;
    if (check(mid)) l = mid; else r = mid;
}

推荐永远用 l + (r-l)/2 防溢出

整数二分先想清楚边界再写 ,模板比 STL 的 lower_bound 更灵活


九、ps

说明
cin 开头必加 ios::sync_with_stdio(false); cin.tie(0);
cin + scanf 混用 绝对不要,同步关了会 RE/读错
vector 越界 [] 不检查,debug 用 .at(i)
map[key] 不存在也会插入默认值 !判存在用 countfind
priority_queueclear 赋值空队列
memset 非 0/-1 只有 0 和 -1 是安全的(按字节),其他用 fill
size() 返回 size_t for(int i=0; i<v.size()-1; i++) 空容器时 size_t 下溢成巨数
多组输入忘了清空 全局 vector/map 不清空 = 经典 WA
int * int 溢出 乘前先 1LL * a * b
lower_bound 无序 不排序用二分必 WA
bitset<N> N 不是变量 想动态用 vector<bool> 或手写 bitset

相关推荐
无聊的菜鸟2 小时前
TMS320F2806X学习笔记(一)—— 了解片上资源
笔记·ti·c2000·f2806x
带多刺的玫瑰3 小时前
Leecode#4刷题之寻找两个正序数组的中位数
java·前端·算法
土司大王3 小时前
LeetCode hot100——除了自身以外数组的乘积
数据结构·算法·leetcode
IvanCodes3 小时前
RAG 实战教程(三):向量数据库检索算法,KNN、IVF、HNSW 与 Faiss 实战
人工智能·算法·agent
优化Henry3 小时前
学习笔记之爱立信站点指向证书执行
运维·服务器·网络·笔记·学习·信息与通信
阿无,3 小时前
布隆过滤器
java·算法·哈希算法
徒慕风流3 小时前
激光雷达回波信号滤波与时刻鉴别算法:原理、代码实现与仿真验证
python·算法·激光雷达
这料鬼有毒3 小时前
二刷hot100-70.爬楼梯
算法
CIO_Alliance4 小时前
AI算法系列(2)| 决策树与随机森林XGBoost:企业AI化转型中的树模型选型逻辑
大数据·人工智能·算法·决策树·系统集成·企业cio联盟·企业级ai化转型