今天开始,把 ACM 学习当成一个长期篇章来写。
这里说的 ACM,不只是在说某一场比赛,更泛指算法竞赛、在线评测和系统性的算法训练。它的价值不只是学几个算法模板,而是训练一种能力:看到一个问题,能读懂约束,抽象模型,判断复杂度,选择合适的数据结构,最后写出稳定可过的代码。
所以第一篇先不急着做题。我们先把地图画出来,知道后面要学什么、先学什么、哪些知识点以后再啃。
一、为什么先写目录
学习最怕的不是不会,而是一直在随机游走。今天看一道动态规划,明天补一个最短路,后天又被网络流吓退。知识点看起来很多,但脑子里没有结构,就很容易越学越散。
目录的作用就是先建立坐标系。以后每一篇文章都要回答三个问题:
- 这个知识点解决哪一类问题;
- 它的核心思想是什么;
- 做题时怎么识别它。
不用一上来追求全会。先知道全图,再一块一块点亮。
二、学习节奏
这个系列会按“基础先稳住,专题再深入”的方式推进。每个专题不追求写成百科,而是尽量写成能拿来学习和复盘的文章。
每篇文章大致固定成这个结构:
- 为什么学:它解决什么问题,不学会卡在哪里;
- 核心思想:尽量用直觉讲清楚,不只背结论;
- 模板代码:沉淀一份可以反复用的写法;
- 典型题:用题目把知识点落下来;
- 易错点:记录边界、复杂度、初始化、溢出这些坑;
- 复盘:这类题以后怎么识别。
三、基础准备
第一阶段先把学习算法竞赛的基本装备准备好。这一层不难,但决定后面能不能写得稳。
- 复杂度分析:时间复杂度、空间复杂度、数据范围反推算法;
- 输入输出:多组数据、EOF、快速输入、格式化输出;
- 基础代码模板:数组、循环、函数、结构体、常用容器;
- 模拟:按题意实现、状态维护、边界处理;
- 排序与二分:二分查找、二分答案、排序后建模;
- 前缀和与差分:区间求和、区间修改、二维前缀和;
- 双指针与滑动窗口:区间移动、单调性、去重与计数;
- 贪心入门:局部选择、交换论证、反例检查。
四、数据结构
数据结构是 ACM 的地基。很多题表面是在讲故事,本质是在问你能不能快速维护某种信息。
- 栈、队列、双端队列;
- 单调栈、单调队列;
- 堆和优先队列;
- 哈希表、集合、映射;
- 并查集;
- 树状数组;
- 线段树;
- ST 表;
- Trie 字典树;
- 分块和莫队;
- 平衡树、Treap、Splay;
- 可持久化线段树、主席树。
五、搜索与动态规划
搜索解决的是“我怎么把所有可能性走完”,动态规划解决的是“我怎么把重复子问题合并掉”。这两块会是中期的重点。
- DFS、BFS 与图/树遍历;
- 回溯、剪枝、迭代加深;
- 记忆化搜索;
- 线性 DP;
- 背包 DP:01 背包、完全背包、多重背包、分组背包;
- 区间 DP;
- 树形 DP;
- 状态压缩 DP;
- 数位 DP;
- 概率与期望 DP;
- DP 优化:滚动数组、单调队列优化、斜率优化入门。
六、图论
图论是 ACM 里最容易成体系的一块。很多问题只要能建成图,后面就能落到遍历、最短路、生成树、匹配、连通性或网络流上。
- 图的存储:邻接表、邻接矩阵、链式前向星;
- 图的遍历:DFS、BFS、连通块;
- 拓扑排序;
- 最短路:Dijkstra、Bellman-Ford、SPFA、Floyd;
- 最小生成树:Kruskal、Prim;
- 二分图判定;
- 二分图最大匹配:匈牙利算法;
- 网络流:最大流、最小割、费用流;
- Tarjan:强连通分量、割点、桥;
- LCA:倍增、Tarjan 离线;
- 树上问题:树的直径、树的重心、树链剖分;
- 差分约束;
- 欧拉路径与哈密顿路径的基本建模。
七、数学
数学专题不一定代码长,但很考验对性质的理解。它经常决定一道题是暴力、模拟,还是一下子变成公式。
- 质数、筛法、约数、最大公约数;
- 快速幂、取模、逆元;
- 扩展欧几里得;
- 中国剩余定理;
- 组合数学:排列组合、Lucas、卡特兰数;
- 容斥原理;
- 矩阵快速幂;
- 线性基;
- 莫比乌斯反演;
- FFT、NTT;
- 博弈论:Nim、SG 函数;
- 概率、期望与随机化算法。
八、字符串
字符串专题很适合单独成体系学。它看起来是处理文本,本质上经常是在处理模式匹配、前缀关系和自动机。
- KMP;
- 字符串哈希;
- Trie;
- AC 自动机;
- Manacher;
- 后缀数组;
- 后缀自动机。
九、计算几何
计算几何不一定最常考,但一旦遇到,就很容易因为精度和边界翻车。这里会以常见模型为主,不一开始追特别偏的题。
- 点、向量、叉积、点积;
- 线段相交;
- 多边形面积;
- 凸包;
- 旋转卡壳;
- 半平面交;
- 最近点对。
十、训练方法
只学知识点还不够,题目练习本身也需要方法。否则很容易出现“题看了很多,但下次还是不会”的情况。
- 如何读题:先看输入范围,再看目标和限制;
- 如何做题:先想暴力,再找优化;
- 如何写题解:写清状态、转移、复杂度和坑点;
- 如何复盘错题:记录错因,而不是只记录答案;
- 如何打周赛和虚拟赛;
- 如何维护自己的模板库;
- 如何建立阶段题单:入门 50 题、基础提升 100 题、专题训练题单。
十一、先从哪里开始
这张目录看起来很长,但真正开始的时候,只需要走第一步。
下一篇先写:
这篇会把学习算法竞赛的基本装备准备好:怎么根据数据范围判断算法,怎么处理输入输出,怎么写一份顺手的代码模板。后面所有题目,都会站在这套基础上往前走。