竞赛代码模板
算法竞赛通用代码模板的结构与使用方法
一句话工具
竞赛代码模板是一份“开题骨架”:先放好头文件、类型别名、调试宏、快读快写和主函数结构,写题时只补核心逻辑。
模板解决的问题
比赛时每道题都要重复写一些固定内容:
- 头文件和命名空间。
- 常用类型别名。
- 全局数组和常量。
- 输入函数。
- 调试输出。
main函数骨架。
这些内容本身不难,但重复手写会浪费注意力,也容易出现细小错误。通用模板的目标是把这些固定部分提前准备好,让写题时把精力放在建模和核心算法上。
模板结构
当前模板大致分成五块:
- 文件头信息:记录作者、题目、OJ、描述等。
- 基础环境:
bits/stdc++.h、using namespace std、typedef long long ll。 - 调试宏:本地开启,提交时可用
ONLINE_JUDGE或NO_DEBUG屏蔽。 - 全局数据区:常量、数组、
n、m等常见变量。 - 主函数骨架:读入、处理、输出。
其中 quickIO 通过模板引用接入:
cpp
1
{{include "code/utils/quick_io.cpp"}}
如果你的代码模板系统会展开这个引用,就能自动把快读快写插入当前位置;如果只是手动复制,则需要把 quickIO 对应代码一并复制进去。
使用步骤
- 复制通用模板。
- 根据题目替换文件头里的
oj、title、description等占位信息。 - 修改
maxn、全局数组和读入变量。 - 在
init或对应位置读入数据。 - 在
main中补上核心算法流程。 - 提交前确认调试输出已关闭。
代码实现
模板文件位置:/code/template/template.cpp。
cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* Author by {{author}} blog: {{blog}} github : {{github}}
* date: {{date}}
* oj: {{oj}}
* title: {{title}}
* description: {{description}}
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// #define NO_DEBUG // switch debug
#if defined(onlinejudge) || defined(ONLINE_JUDGE) || defined(NO_DEBUG)
#define log(...)
#define fenc
#else
#define log(args...) { cout << "LINE:" << __LINE__ << " : ";string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
#define fenc cout<<"================================";
void err(istream_iterator<string> it) {}
template<typename T>
void err(istream_iterator<string> it, T a) {
cerr << *it << " = " << a << "\n";
}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
cerr << *it << " = " << a << ", ";
err(++it, args...);
}
#endif
const int maxn = 1e6+5;
int n,m;
int a[maxn];
{{include "code/utils/quick_io.cpp"}}
void init() {
read(n);
CURRENT_LINE
}
signed main () {
#ifdef FREOPEN
freopen("in", "r",stdin);
#endif
// std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); // 关闭io同步
return 0;
}
常见改法
不使用 quickIO
如果题目输入规模不大,可以删除 quickIO 引用,改用标准流:
cpp
1
2
ios::sync_with_stdio(false);
cin.tie(nullptr);
这样代码更短,也更适合字符串、浮点数、混合输入等场景。
调整调试宏
模板里通过 NO_DEBUG 和 ONLINE_JUDGE 控制调试输出。常见做法是本地默认开启,提交时自动关闭:
cpp
1
2
3
#if defined(ONLINE_JUDGE)
#define log(...)
#endif
如果某个 OJ 没有定义 ONLINE_JUDGE,可以在提交前手动加上:
cpp
1
#define NO_DEBUG
改成多测试用例结构
如果题目有多组数据,可以把核心逻辑封装成 solve():
cpp
1
2
3
4
5
6
7
8
9
10
11
void solve() {
// read one test case
// solve one test case
}
int main() {
int T;
read(T);
while (T--) solve();
return 0;
}
注意事项
- 通用模板不是越大越好,只保留高频、低风险、你真的熟悉的内容。
maxn要按题目约束调整,避免数组过小越界,也避免盲目开过大的全局数组。- 如果模板里含有占位符,提交前必须替换干净。
- 调试宏不要把信息输出到正式答案里。
- 不同题目的输入输出特点不同,quickIO 和标准流不要机械套用。
维护方式
后续如果要修改通用头文件、常用类型别名、输入输出设置,请直接修改上面的代码文件。文章只负责解释模板的结构和使用方法,真正可复制的代码以 book/code/template/template.cpp 为准。