系列导航:
- [第一篇] 基础语法与竞赛优势
- [第二篇] 动态数组与字符串革命
- [第三篇] 映射与集合的终极形态
- [第四篇] STL算法与迭代器
- [第五篇] 现代语法糖精粹
- [▶ 本篇] 竞赛实战技巧
一、输入输出终极优化
1.1 加速cin/cout(必须掌握!)
int main() {ios::sync_with_stdio(false); // 关闭与C标准库的同步cin.tie(nullptr); // 解除cin与cout的绑定cout.tie(nullptr); // 可选,解除cout与其他流的绑定// 之后的cin/cout速度与scanf/printf相当
}
原理剖析:
- sync_with_stdio(false):禁用C++流与C流的同步机制
- tie(nullptr):解除输入输出流之间的默认关联
- 效果:处理1e6数据量时,耗时从1200ms → 200ms
1.2 快速读写模板(针对大数据量)
inline int read() {int x=0; bool f=0; char c=getchar();while(c<'0' || c>'9') { f |= (c=='-'); c=getchar(); }while(c>='0' && c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return f ? -x : x;
}inline void write(int x) {if(x<0) putchar('-'), x=-x;if(x>9) write(x/10);putchar(x%10+'0');
}// 使用示例
int n = read();
write(n);
性能对比(读取1e6个int):
方式 | 耗时 |
---|---|
cin(未加速) | 1200ms |
cin(加速) | 200ms |
快速读入 | 80ms |
二、调试技巧大全
2.1 条件编译调试
#define DEBUG 1 // 1开启调试模式,0关闭#if DEBUG
#define debug(x) cerr << #x << " = " << x << endl
#else
#define debug(x)
#endif// 使用示例
int a = 42;
debug(a); // 输出:a = 42
2.2 容器内容打印
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {os << "[";for(auto it=vec.begin(); it!=vec.end(); ++it) {os << *it << (it+1 != vec.end() ? ", " : "");}os << "]";return os;
}// 使用示例
vector<int> test{1,2,3};
cout << test; // 输出:[1, 2, 3]
2.3 内存泄漏检测(本地调试)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>int main() {_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// ...你的代码...return 0;
}
三、STL使用避坑指南
3.1 vector迭代器失效场景
vector<int> vec = {1,2,3,4,5};
auto it = vec.begin() + 2;vec.push_back(6); // 可能导致迭代器失效!
cout << *it; // 未定义行为
安全操作原则:
- 插入/删除操作后,所有迭代器可能失效
- 修改容量(reserve/resize)后,所有迭代器失效
- 正确做法:在修改后重新获取迭代器
3.2 map/unordered_map的查找陷阱
unordered_map<string, int> dict;// 错误方式:直接用[]
if(dict["key"]) { // 会自动插入"key"并初始化为0// ...
}// 正确方式:使用find
if(dict.find("key") != dict.end()) {// ...
}
3.3 priority_queue的比较函数
// 小根堆的正确声明方式
priority_queue<int, vector<int>, greater<int>> minHeap;// 自定义比较函数
struct Compare {bool operator()(const Node& a, const Node& b) {return a.val > b.val; // 注意是>号!}
};
priority_queue<Node, vector<Node>, Compare> customHeap;
四、内存管理进阶技巧
4.1 vector预分配策略
vector<int> vec;
vec.reserve(1e6); // 预分配空间(不初始化元素)// 对比C实现
int* arr = (int*)malloc(1e6 * sizeof(int));
4.2 内存池技术(适用于频繁申请释放)
const int POOL_SIZE = 1e6;
Node pool[POOL_SIZE];
int ptr = 0;Node* newNode() {return &pool[ptr++];
}// 使用示例
Node* node = newNode();
4.3 移动语义优化
vector<string> processBigData() {vector<string> data(1e6);// ...处理数据...return move(data); // 触发移动而非拷贝
}
五、模板与宏的妙用
5.1 泛型快速读入
template<typename T>
inline T read() {T x=0; bool f=0; char c=getchar();while(c<'0' || c>'9') { f|=(c=='-'); c=getchar(); }while(c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return f?-x:x;
}// 使用示例
long long n = read<long long>();
5.2 调试宏进阶版
#define dbg(...) cerr << "Line " << __LINE__ << ": " \<< #__VA_ARGS__ << " = " \<< dump(__VA_ARGS__) << endl// 支持容器打印的dump函数
template<typename T> string dump(const T& x);
template<> string dump(const vector<int>& v) { /* 实现 */ }
六、常见错误代码模式
6.1 整数溢出
int a = 1e9, b = 1e9;
int c = a * b; // 溢出!
// 正确:使用long long
long long c = (long long)a * b;
6.2 越界访问
vector<int> vec(10);
cout << vec[10]; // 越界!
// 正确:使用vec.at(10)或检查索引
6.3 未初始化变量
int sum; // 未初始化!
for(int x : vec) sum += x;
// 正确:int sum = 0;
七、竞赛必备代码模板大全
7.1 输入输出终极优化模板
7.1.1 通用加速头
#include <bits/stdc++.h>
using namespace std;struct FastIO {FastIO() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cout << fixed << setprecision(10);}
} FAST_IO;
功能说明:
- 禁用C/C++流同步(提速关键)
- 解除cin/cout绑定(减少flush开销)
- 全局浮点数输出格式设置
- 通过结构体构造函数实现自动初始化
7.1.2 快速读写模板
// 整数读入(支持负数)
template<typename T>
inline T read() {T x = 0; bool f = 0; char c = getchar();while (c < '0' || c > '9') { if (c == '-') f = 1; c = getchar(); }while (c >= '0' && c <= '9') x = (x<<3) + (x<<1) + (c^48), c = getchar();return f ? -x : x;
}// 整数输出(兼容所有整型)
template<typename T>
inline void write(T x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');
}// 使用示例
int main() {int n = read<int>();long long sum = read<long long>();write(n); putchar(' ');write(sum);return 0;
}
7.2 数据结构初始化模板
7.2.1 邻接表(图论通用)
const int MAXN = 1e5+5;
vector<vector<pair<int, int>>> graph(MAXN); // 邻接表[结点] = {邻接结点, 边权}inline void addEdge(int u, int v, int w) {graph[u].emplace_back(v, w);graph[v].emplace_back(u, w); // 无向图
}// 使用示例
void initGraph() {addEdge(1, 2, 5);addEdge(2, 3, 3);
}
7.2.2 并查集(路径压缩+按秩合并)
struct DSU {vector<int> parent, rank;DSU(int n) : parent(n+1), rank(n+1, 1) {iota(parent.begin(), parent.end(), 0);}int find(int x) {return parent[x] == x ? x : parent[x] = find(parent[x]);}bool unite(int x, int y) {x = find(x), y = find(y);if(x == y) return false;if(rank[x] < rank[y]) swap(x, y);parent[y] = x;rank[x] += rank[y];return true;}
};// 使用示例
DSU dsu(100000);
dsu.unite(1, 2);
if(dsu.find(1) == dsu.find(2)) cout << "Connected";
7.3 算法模板精选
7.3.1 Dijkstra最短路径(优先队列优化)
vector<int> dijkstra(int start, int n) {vector<int> dist(n+1, INT_MAX);priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;dist[start] = 0;pq.emplace(0, start);while(!pq.empty()) {auto [d, u] = pq.top(); pq.pop();if(d > dist[u]) continue;for(auto [v, w] : graph[u]) {if(dist[v] > dist[u] + w) {dist[v] = dist[u] + w;pq.emplace(dist[v], v);}}}return dist;
}
7.3.2 快速幂(取模版)
const int MOD = 1e9+7;long long fastPow(long long base, long long exp) {long long res = 1;base %= MOD;while(exp > 0) {if(exp & 1) res = (res * base) % MOD;base = (base * base) % MOD;exp >>= 1;}return res;
}// 使用示例
cout << fastPow(2, 1e18); // 计算2^1e18 mod 1e9+7
7.4 调试与测试模板
7.4.1 自动化调试宏
#ifdef DEBUG
#define debug(...) \do { \cerr << "Line " << __LINE__ << ": " \<< #__VA_ARGS__ << " -> "; \_debug(__VA_ARGS__); \} while(0)template<typename T> void _debug(T x) { cerr << x << endl; }
template<typename T, typename... Args>
void _debug(T x, Args... args) { cerr << x << ", "; _debug(args...); }
#else
#define debug(...)
#endif// 使用示例
int a = 5, b = 3;
debug(a, b, a+b); // 输出:Line 20: a, b, a+b -> 5, 3, 8
7.4.2 随机测试数据生成
vector<int> generateTestData(int n, int minVal, int maxVal) {random_device rd;mt19937 gen(rd());uniform_int_distribution<> dis(minVal, maxVal);vector<int> data(n);generate(data.begin(), data.end(), [&](){ return dis(gen); });return data;
}// 使用示例
auto testCase = generateTestData(100000, 1, 1e9);
7.5 实用工具模板
7.5.1 时间测量工具
class Timer {chrono::high_resolution_clock::time_point start;
public:Timer() : start(chrono::high_resolution_clock::now()) {}double elapsed() const {auto end = chrono::high_resolution_clock::now();return chrono::duration<double>(end - start).count();}void reset() { start = chrono::high_resolution_clock::now(); }
};// 使用示例
Timer timer;
// ...代码段...
cout << "耗时:" << timer.elapsed() << "秒";
7.5.2 容器内容打印
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {os << "[";for(auto it = vec.begin(); it != vec.end(); ++it) {os << *it << (it+1 != vec.end() ? ", " : "");}return os << "]";
}// 使用示例
vector<int> arr{1,3,5,7};
cout << arr; // 输出:[1, 3, 5, 7]
7.6 内存管理模板
7.6.1 矩阵快速分配
vector<vector<int>> createMatrix(int rows, int cols, int initVal = 0) {return vector<vector<int>>(rows, vector<int>(cols, initVal));
}// 使用示例
auto matrix = createMatrix(1000, 1000); // 1000x1000零矩阵
7.6.2 链式前向星(图论高频访问优化)
struct Edge {int to, w, next;
};vector<Edge> edges;
vector<int> head;void addEdge(int u, int v, int w) {edges.push_back({v, w, head[u]});head[u] = edges.size()-1;
}// 初始化
head.resize(MAXN, -1);// 遍历u的邻接边
for(int i = head[u]; ~i; i = edges[i].next) {auto [v, w, _] = edges[i];// 处理边u->v
}
7.7 模板使用黄金法则
- 提前测试:在本地验证模板正确性
- 适度修改:根据题目需求调整模板参数
- 内存预判:大数据量前调用reserve/resize
- 版本检查:确认OJ支持C++11/17特性
- 备份策略:保存常用模板集合
- 注释开关:通过宏控制调试输出
通过掌握这些模板,您将能够:
- 节省80%的代码编写时间
- 避免常见底层错误
- 快速应对各类算法问题
- 保持代码整洁易维护
系列总结
通过本系列六篇文章,你已经掌握:
- 现代C++核心语法 ✔️
- STL容器与算法 ✔️
- 竞赛优化技巧 ✔️
- 调试与错误处理 ✔️
- 高效编码模式 ✔️
在评论区分享你的学习心得或遇到的难题,作者将挑选优质问题进行专题补充讲解!愿你在算法竞赛中所向披靡,AC永随!🚀