C++竞赛必备代码模板
C++ 算法竞赛常用核心代码模板
1. 头文件与优化(竞赛标配)
几乎所有竞赛代码都以此开头,用于关闭同步、加速输入输出。
#include <bits/stdc++.h> // 万能头文件,包含所有标准库(竞赛可用,工程慎用) using namespace std; // 输入输出优化(对大量数据至关重要) int main() { ios::sync_with_stdio(false); // 关闭C与C++输入输出的同步,加速 cin.tie(nullptr); // 解绑cin和cout,进一步加速 cout.tie(nullptr); // 解绑cout,可选 // ... 你的代码逻辑 ... return 0; }2. 快速读取整数(当cin优化后仍不够快时)
适用于需要读取数百万个整数的极端情况。
int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); } return x * f; } // 使用:int n = read();3. 常用数据结构初始化与使用
Vector(动态数组):
vector<int> v; v.push_back(1); // 尾部插入 int x = v.back(); // 获取尾部元素 v.pop_back(); // 弹出尾部元素 sort(v.begin(), v.end()); // 排序 // 初始化一个大小为n,值全为0的vector vector<int> arr(n, 0);String(字符串):
string s = "hello"; s += " world"; // 拼接 s.substr(0, 5); // 取子串,从0开始取5个字符 -> "hello" int len = s.length(); // 长度 getline(cin, s); // 读取一行(包含空格)Map(哈希表/键值对):
unordered_map<int, string> mp; // 无序哈希表,O(1)操作(平均) mp[1] = "one"; // 插入或修改 if (mp.count(1)) { /* 键1存在 */ } for (auto& [key, value] : mp) { /* C++17结构化绑定遍历 */ }Set(集合):
set<int> s; // 有序集合,基于红黑树,O(log n) s.insert(3); s.erase(3); if (s.find(3) != s.end()) { /* 存在 */ } // 无序集合(更快,但元素无顺序) unordered_set<int> us;4. 算法模板
二分查找(在有序数组arr中查找第一个>=target的元素位置):
int lower_bound(vector<int>& arr, int target) { int left = 0, right = arr.size(); // 注意right初始值 while (left < right) { int mid = left + (right - left) / 2; // 防止溢出 if (arr[mid] >= target) { right = mid; } else { left = mid + 1; } } return left; // 返回索引,如果target大于所有元素,则返回arr.size() }并查集 (Disjoint Set Union, DSU):
class DSU { vector<int> parent; public: DSU(int n) : parent(n) { iota(parent.begin(), parent.end(), 0); // parent[i] = i } int find(int x) { // 路径压缩 return parent[x] == x ? x : parent[x] = find(parent[x]); } void unite(int x, int y) { x = find(x); y = find(y); if (x != y) parent[y] = x; // 将y的根连接到x的根上 } };快速幂(计算 a^b % mod):
long long fastPow(long long a, long long b, long long mod) { long long res = 1 % mod; // 处理mod=1的情况 a %= mod; while (b > 0) { if (b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1; } return res; }5. 实用代码片段
遍历Map/Set:
// 传统方式 for (auto it = mp.begin(); it != mp.end(); ++it) { cout << it->first << " " << it->second << endl; } // C++11 范围for循环 for (const auto& kv : mp) { cout << kv.first << " " << kv.second << endl; } // C++17 结构化绑定(最清晰) for (const auto& [key, value] : mp) { cout << key << " " << value << endl; }输出保留小数:
double ans = 3.1415926; cout << fixed << setprecision(2) << ans << endl; // 输出:3.14获取数组/容器最大值最小值:
vector<int> v = {1, 5, 3, 2}; int maxVal = *max_element(v.begin(), v.end()); // 5 int minVal = *min_element(v.begin(), v.end()); // 1总结与建议:
- 竞赛核心:
#include <bits/stdc++.h>+using namespace std;+ios::sync_with_stdio(false);是竞赛C++代码的“起手式”。 - 熟练工具:务必熟练掌握
vector,string,map/set及其无序版本unordered_map/unordered_set的常用操作。 - 掌握模板:二分、并查集、快速幂、前缀和/差分是解决许多中高难度题目的基础组件,理解后要能默写。
- 多练多用:将这些代码片段在实际解题中反复运用,形成肌肉记忆。
