一份按知识点和章节组织的算法入门题单。保留题目、学习资料与题解的外部链接,并提供可离线使用的交互网页。
| 路线 | 章节 | 题量 | 练习重点 |
|---|---|---|---|
| LeetCode 算法主线 | 18 | 160 | 常见模型、数据结构与解题方法 |
| AtCoder · 洛谷 | 12 | 80 | 完整程序、输入输出与综合应用 |
| Codeforces 入门 | 3 | 18 | 读题、观察、构造与基础竞赛题 |
共 236 道不同题目:138 道 LeetCode、40 道 AtCoder、40 道洛谷、18 道 Codeforces。22 道题跨路线共享,完成一次即可。
阅读题单: 在下方选择路线,展开章节。每章包含学习目标、C++ 工具、阅读入口、题目和过关标准。
交互网页: 下载仓库后,在浏览器中打开 index.html。支持章节切换、搜索、状态筛选、复盘笔记及进度导入导出,无需安装依赖。
网页不内置完成记录,进度只保存在当前浏览器中,不上传到仓库或服务器。换浏览器或设备前,可导出进度后再导入;导出的文件可能包含自己的笔记,请自行保存。
- 准备系统练习算法: 从算法主线开始,按章节理解模型与实现。
- 需要练完整程序: 从 AtCoder · 洛谷第 1 章开始,补齐输入输出、多组测试和边界调试。
- 准备接触竞赛: 能独立完成完整程序和简单题后,进入 Codeforces 入门;专题练习与整场训练可以穿插进行。
| 标记 | 建议做法 |
|---|---|
| 快练 | 独立实现,确认基本操作与边界 |
| 精做 / 主练 | 解释关键思路、正确性、时间与空间复杂度 |
| 选做 | 根据知识缺口选择,入门阶段可后置 |
| 共享题 | 两条路线使用同一道题,网页同步状态与笔记 |
先独立尝试,再按需要阅读提示和题解。提示后完成的题,可间隔其他练习后闭卷复测。通过评测是反馈之一,能解释并独立实现才是学习目标。
按专题建立算法与数据结构的知识体系,包含 138 道 LeetCode 与 22 道完整程序练习。
| 章节 | 内容 | 题量 |
|---|---|---|
| 01 | 模拟、数组与枚举 | 11 |
| 02 | 哈希与计数 | 8 |
| 03 | 双指针与滑动窗口 | 8 |
| 04 | 前缀和与差分 | 6 |
| 05 | 二分查找与二分答案 | 11 |
| 06 | 链表与指针 | 9 |
| 07 | 栈、堆与单调结构 | 11 |
| 08 | 排序、分治与贪心 | 10 |
| 09 | 位运算与基础数学 | 9 |
| 10 | 树、递归与子问题返回值 | 15 |
| 11 | 图遍历、BFS 与拓扑排序 | 10 |
| 12 | 搜索、回溯与剪枝 | 10 |
| 13 | 并查集、最短路与最小生成树 | 8 |
| 14 | 基础动态规划 | 11 |
| 15 | 背包、计数与状态设计 | 9 |
| 16 | 子序列、区间与树形 DP | 7 |
| 17 | KMP 与字典树 | 3 |
| 18 | 树状数组与线段树 | 4 |
01 · 模拟、数组与枚举 · 11 题
学习目标: 根据文字规则实现程序,并从约束缩小枚举范围。
C++ 工具: vector、string、引用、size 与 reserve、标准输入输出。
阅读入口
- 进入本章: 数组理论基础。只复查连续存储、下标、插入删除;已能解释的部分直接略过。
- 做 ABC083B 前: OI Wiki:枚举 · 官网。只看枚举的要点:解空间、枚举范围、减少自由变量;先不看例题代码。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 001 | PracticeA · Welcome to AtCoder | 快练 · 共享 | 标准输入输出与精确输出格式;不使用 LeetCode 的 Solution 模板。 | 对应方法 · 备用 |
| 002 | LC 27 · 移除元素 | 精做 | 快慢指针维护有效前缀,区分返回长度与修改原数组。 | 题解 |
| 003 | LC 283 · 移动零 | 快练 | 保持非零元素的相对顺序,比较交换与覆盖。 | 题解 |
| 004 | LC 26 · 删除有序数组中的重复项 | 快练 | 有序性怎样帮助去重;写指针代表什么。 | 题解 |
| 005 | LC 977 · 有序数组的平方 | 精做 | 利用两端绝对值,从结果数组末尾填入。 | 题解 |
| 006 | LC 344 · 反转字符串 | 快练 | 左右指针与奇偶长度边界。 | 题解 |
| 007 | LC 59 · 螺旋矩阵 II | 精做 | 逐层填数,写清每条边的开闭范围。 | 题解 · 备用 |
| 008 | LC 54 · 螺旋矩阵 | 精做 | 从生成矩阵迁移到遍历矩阵;单行、单列不能重复访问。 | 题解 · 备用 |
| 009 | ABC083B · Some Sums | 精做 · 共享 | 枚举整数并拆数位,明确取模与整除各自的作用。 | 对应方法 · 备用 |
| 010 | ABC085C · Otoshidama | 精做 · 共享 | 用数量约束消去一个变量,检验无解与零张数。 | 对应方法 · 备用 |
| 011 | ABC086C · Traveling | 精做 · 共享 | 由曼哈顿距离与奇偶性推导可达条件,避免逐步模拟时间。 | 对应方法 · 备用 |
过关标准: 能独立写标准输入输出程序;解释有效数组前缀;把三重枚举降成两重,并算清操作次数。
02 · 哈希与计数 · 8 题
学习目标: 从逐对比较转为记录信息;区分频次数组、集合、映射的用途。
C++ 工具: unordered_map、unordered_set、find、count、pair;哈希平均成本与最坏成本不同。
阅读入口
- 进入本章: 哈希表理论基础。看数组、set、map 各适合记录什么;只读 C++,暂不深挖哈希表源码。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 012 | LC 242 · 有效的字母异位词 | 快练 | 字符频次,使用 26 个槽位前先确认字符范围。 | 题解 |
| 013 | LC 383 · 赎金信 | 快练 | 从频次相等改为库存足够。 | 题解 |
| 014 | LC 349 · 两个数组的交集 | 快练 | 集合去重与交集;比较计数数组和集合。 | 题解 |
| 015 | LC 217 · 存在重复元素 | 快练 | 用集合判断重复,注意空间成本。 | 题解 |
| 016 | LC 1 · 两数之和 | 精做 | 查询补数后再插入,避免同一元素使用两次。 | 题解 |
| 017 | LC 49 · 字母异位词分组 | 精做 | 设计同组字符串的共同键,计入排序或计数键的成本。 | 题解 |
| 018 | LC 128 · 最长连续序列 | 精做 | 只从连续段起点向后找;解释为什么不是平方复杂度。 | 题解 · 备用 |
| 019 | LC 454 · 四数相加 II | 精做 | 把四数组配对拆为两组和;估计 O(n²) 时间和空间。 | 题解 · 备用 |
过关标准: 能说明查询和插入的先后顺序;能为哈希键构造、排序与存储分别计成本。
03 · 双指针与滑动窗口 · 8 题
学习目标: 能解释何时移动哪个指针,以及移动后为什么不会漏解。
C++ 工具: sort、字符计数、string 下标;注意排序对后续指针移动的影响。
阅读入口
- 尝试 167 后: 167 两数之和 II - 输入有序数组:对应讲解。只看利用有序性排除候选的证明,再回到自己的指针更新条件。
- 尝试 209 后: 209 长度最小的子数组:对应讲解。看窗口表示的区间与收缩条件,再关掉题解重写。
- 尝试 3 后: 3 无重复字符的最长子串:对应讲解。比较频次维护与最后出现位置两种思路,只先写熟一种。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 020 | LC 167 · 两数之和 II - 输入有序数组 | 精做 | 有序数组配对;论证和偏小时为什么移动左端。 | 题解 |
| 021 | LC 15 · 三数之和 | 精做 | 排序、固定一个数、双指针;区分不同层的去重。 | 题解 |
| 022 | LC 11 · 盛最多水的容器 | 精做 | 证明移动较短边不会错过更优解。 | 题解 · 备用 |
| 023 | LC 643 · 子数组最大平均数 I | 快练 | 固定长度窗口,维护加入和移出的元素。 | 题解 |
| 024 | LC 209 · 长度最小的子数组 | 精做 | 正数数组中的最短可行窗口;不要把方法套到任意负数数组。 | 题解 |
| 025 | LC 3 · 无重复字符的最长子串 | 精做 | 维护窗口内字符不重复;循环收缩直到重新合法。 | 题解 |
| 026 | LC 438 · 找到字符串中所有字母异位词 | 精做 | 固定窗口频次与目标频次匹配。 | 题解 · 备用 |
| 027 | LC 567 · 字符串的排列 | 快练 | 将“返回所有起点”迁移为“是否存在”,闭卷完成。 | 题解 · 备用 |
过关标准: 能区分固定窗口、可变窗口、左右夹逼;解释 209 的正数条件为何关键。
04 · 前缀和与差分 · 6 题
学习目标: 把反复区间查询、批量区间修改转为预处理与端点更新。
C++ 工具: 二维 vector、long long、0/1 下标转换。
阅读入口
- 做 303 前: OI Wiki:前缀和与差分 · 官网。只看一维前缀和;用长度 n+1 的数组写出闭区间求和。
- 做 304 前: OI Wiki:前缀和与差分 · 官网。再看二维前缀和,用重叠区域解释容斥。
- 做 1109 前: OI Wiki:前缀和与差分 · 官网。读差分与前缀和的互逆关系;到 P3397 前再读二维差分。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 028 | LC 303 · 区域和检索 - 数组不可变 | 快练 | 前缀和一次预处理、多次查询;空前缀初始化。 | 题解 |
| 029 | LC 304 · 二维区域和检索 - 矩阵不可变 | 精做 | 二维前缀和与矩形查询,边界补零。 | 题解 · 备用 |
| 030 | LC 560 · 和为 K 的子数组 | 精做 | 前缀和配对加频次哈希;允许负数,不能直接套普通滑窗。 | 题解 |
| 031 | LC 1109 · 航班预订统计 | 精做 | 区间加的差分端点更新,最后统一还原。 | 题解 · 备用 |
| 032 | LC 1094 · 拼车 | 精做 | 上下车事件和容量检查,注意终点下车不占后续位置。 | 题解 · 备用 |
| 033 | P3397 · 地毯 | 精做 · 共享 | 二维差分四角更新,再通过二维前缀和恢复覆盖次数。 | 对应方法 · 备用 |
过关标准: 能闭卷推导二维前缀和的加减关系和差分四角;解释 560 为什么先查再加频次。
05 · 二分查找与二分答案 · 11 题
学习目标: 从找下标过渡到找最小可行答案;先证明单调性再二分。
C++ 工具: lower_bound、upper_bound、避免溢出的中点、整数上取整。
阅读入口
- 做 704 前: OI Wiki:二分 · 官网。看整数区间二分与边界;先固定一种区间约定,不同时背多个模板。
- 做 875 前: OI Wiki:二分 · 官网。再看二分答案:答案范围、判定函数、单调性;暂不读三分。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 034 | LC 704 · 二分查找 | 快练 | 手写二分,检查单元素与找不到的情况。 | 题解 |
| 035 | LC 35 · 搜索插入位置 | 快练 | 第一个不小于目标的位置,允许答案为 n。 | 题解 |
| 036 | LC 34 · 在排序数组中查找元素的第一个和最后一个位置 | 精做 | 左右边界,处理全部相同、目标缺失。 | 题解 |
| 037 | LC 744 · 寻找比目标字母大的最小字母 | 快练 | 严格大于与不小于的区别,以及循环回到首字符。 | 题解 · 备用 |
| 038 | LC 74 · 搜索二维矩阵 | 精做 | 把二维有序结构映射成一维下标。 | 题解 · 备用 |
| 039 | LC 153 · 寻找旋转排序数组中的最小值 | 精做 | 利用旋转数组分段有序,判断最小值所在侧。 | 题解 · 备用 |
| 040 | LC 33 · 搜索旋转排序数组 | 精做 | 判断哪半段有序,再判断目标是否在其中。 | 题解 · 备用 |
| 041 | LC 162 · 寻找峰值 | 精做 | 沿斜率寻找局部峰;不要误称整个谓词天然单调。 | 题解 · 备用 |
| 042 | LC 875 · 爱吃香蕉的珂珂 | 精做 | 把速度转为耗时可行性,累加耗时用足够宽的整数。 | 题解 · 备用 |
| 043 | LC 1011 · 在 D 天内送达包裹的能力 | 精做 | 把容量转为天数判定;保持货物原顺序。 | 题解 · 备用 |
| 044 | LC 410 · 分割数组的最大值 | 选做 | 与 1011 对照;说明非负数条件下“至多 k 段”与细分为 k 段的关系。 | 题解 · 备用 |
过关标准: 能解释区间不变量与循环结束返回值;能自己写一个答案判定函数并证明单调。
06 · 链表与指针 · 9 题
学习目标: 理解链表的指针关系,独立实现常见操作并处理边界。
C++ 工具: ListNode*、虚拟头、引用与指针传参、对象生命周期。
阅读入口
- 进入本章: 链表理论基础。只复查插入删除、虚拟头与存储方式;遇断链必须画图。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 045 | LC 203 · 移除链表元素 | 快练 | 虚拟头统一头节点删除与中间删除。 | 题解 |
| 046 | LC 206 · 反转链表 | 精做 | 先保存后继再改 next,明确三个指针含义。 | 题解 |
| 047 | LC 21 · 合并两个有序链表 | 快练 | 有序链表归并与剩余部分连接。 | 题解 |
| 048 | LC 876 · 链表的中间结点 | 快练 | 快慢指针,约定偶数长度的中点。 | 题解 |
| 049 | LC 141 · 环形链表 | 快练 | 相遇判环,访问 next 前判断合法性。 | 题解 |
| 050 | LC 19 · 删除链表的倒数第 N 个结点 | 精做 | 保持指针间距,覆盖删除头节点。 | 题解 |
| 051 | LC 142 · 环形链表 II | 精做 | 用路程关系推导环入口,不能只背相遇后移动规则。 | 题解 |
| 052 | LC 24 · 两两交换链表中的节点 | 精做 | 局部交换前保留前驱与后继,处理奇数尾节点。 | 题解 |
| 053 | LC 234 · 回文链表 | 选做 | 中点、反转、比较组合应用;说明是否恢复原链表。 | 题解 · 备用 |
过关标准: 能画出每次改 next 前后的关系;解释空链表、单节点与头节点删除。
07 · 栈、堆与单调结构 · 11 题
学习目标: 从容器操作进入“保留哪些候选、何时淘汰候选”的思考。
C++ 工具: stack、queue、deque、priority_queue、greater;pop 不返回元素。
阅读入口
- 做 20 前: 栈与队列理论基础。看容器接口与栈/队列行为,不必手写所有底层实现。
- 做 1046 前: Hello 算法:堆。看大小顶堆、插入删除、建堆和 C++ priority_queue 用法。
- 做 496 前: 代码随想录:每日温度中的单调栈入门。只读“单调栈适用什么问题”和栈存下标的意义;不提前读 739 的完整代码。
- 尝试 347 后: NeetCode:前K个高频元素的堆法与频率分桶。堆法先理解;再读频率桶,解释哈希统计加桶为什么平均 O(n)。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 054 | LC 20 · 有效的括号 | 快练 | 括号类型匹配与空栈边界。 | 题解 |
| 055 | LC 1047 · 删除字符串中的所有相邻重复项 | 快练 | 用栈消除相邻元素,不反复删除字符串中部。 | 题解 |
| 056 | LC 150 · 逆波兰表达式求值 | 精做 | 后缀表达式求值,减法除法的操作数顺序。 | 题解 |
| 057 | LC 232 · 用栈实现队列 | 快练 | 双栈队列;摊还成本不等于每次操作都 O(1)。 | 题解 |
| 058 | LC 155 · 最小栈 | 精做 | 普通栈与最小值信息同步,处理重复最小值。 | 题解 |
| 059 | LC 1046 · 最后一块石头的重量 | 快练 | 最大堆模拟;区分建堆与反复插入的成本。 | 题解 |
| 060 | LC 347 · 前 K 个高频元素 | 精做 | 频次统计加 Top K;堆法基线后补频率桶,满足优于 O(n log n) 的目标。 | 题解 |
| 061 | LC 496 · 下一个更大元素 I | 精做 | 单调栈维护还没找到答案的下标。 | 题解 |
| 062 | LC 739 · 每日温度 | 精做 | 从找数值迁移到找距离;解释何时出栈。 | 题解 |
| 063 | LC 239 · 滑动窗口最大值 | 选做 | 单调队列同时处理失效下标和劣势候选。 | 题解 · 备用 |
| 064 | LC 84 · 柱状图中最大的矩形 | 选做 | 左右第一个更小位置、哨兵与等高柱子的边界约定。 | 题解 · 备用 |
过关标准: 能用每个元素最多进出一次解释单调结构的线性复杂度;能分析堆操作总成本。
08 · 排序、分治与贪心 · 10 题
学习目标: 把排序作为组织信息的手段;每个贪心选择都要给出局部交换或覆盖证明。
C++ 工具: sort 比较器必须严格;明确递归函数的含义与终止条件。
阅读入口
- 做 912 前: Hello 算法:快速排序 · 官网。看划分、递归边界、退化情况;理解三数取中,但不混用不同 partition 约定。
- 做 455 前: 贪心算法理论基础。看局部最优与整体最优的联系,避免“感觉可行”当证明。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 065 | LC 912 · 排序数组 | 精做 | 先独立实现归并排序;再用快排巩固划分,分析重复元素与最坏情况。 | 题解 · 备用 |
| 066 | LC 215 · 数组中的第K个最大元素 | 精做 | 先用堆理解,再学快速选择;平均 O(n),最坏 O(n²),不能把堆法当作线性算法。 | 题解 |
| 067 | LC 455 · 分发饼干 | 快练 | 排序后匹配最小可满足对象。 | 题解 |
| 068 | LC 121 · 买卖股票的最佳时机 | 快练 | 记录此前最低价,区分买入在卖出之前。 | 题解 |
| 069 | LC 55 · 跳跃游戏 | 精做 | 维护当前能够覆盖的最远位置。 | 题解 |
| 070 | LC 45 · 跳跃游戏 II | 精做 | 按可达区间分层推进,解释增加一次跳跃的时机。 | 题解 · 备用 |
| 071 | LC 56 · 合并区间 | 精做 | 按左端点排序后合并,确认端点相等是否重叠。 | 题解 |
| 072 | LC 435 · 无重叠区间 | 精做 | 按结束时间选区间,给出交换论证。 | 题解 |
| 073 | LC 452 · 用最少数量的箭引爆气球 | 精做 | 与 435 对照端点相等的含义,避免直接复制条件。 | 题解 · 备用 |
| 074 | LC 763 · 划分字母区间 | 精做 | 最后出现位置决定当前段必须延伸到哪里。 | 题解 · 备用 |
过关标准: 能区分归并与快排成本;会构造一个反例推翻错误的贪心排序规则。
09 · 位运算与基础数学 · 9 题
学习目标: 理解整数算法与基础数学:位操作、gcd、筛法与快速幂。
C++ 工具: 无符号位运算、long long、整数除法、std::gcd(C++17);按平台支持选择标准。
阅读入口
- 做 136 前: OI Wiki:位操作 · 官网。只看异或、移位、清除最低位 1;暂不读高级二进制技巧。
- 做 1979 前: OI Wiki:最大公约数 · 官网。看欧几里得算法及 gcd 与 lcm;扩展欧几里得留到后续专题。
- 做 204 前: OI Wiki:筛法 · 官网。先读埃氏筛;只有做 P3383 时再读线性筛与大规模空间开销。
- 做 50 前: OI Wiki:快速幂 · 官网。读按二进制拆指数与迭代快速幂;做 P1226 时加入取模。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 075 | LC 136 · 只出现一次的数字 | 快练 | 异或的抵消规律,解释前提是其余数字恰好成对。 | 题解 · 备用 |
| 076 | LC 191 · 位 1 的个数 | 快练 | 清掉最低位 1,注意整数位宽和符号。 | 题解 · 备用 |
| 077 | LC 338 · 比特位计数 | 精做 | 从去掉最低位 1 的数推出计数;此处只掌握递推,不展开整章 DP。 | 题解 · 备用 |
| 078 | LC 1979 · 找出数组的最大公约数 | 快练 | 题目要求最小数与最大数的 gcd,不是整个数组的 gcd;手写辗转相除。 | 题解 · 备用 |
| 079 | LC 204 · 计数质数 | 精做 | 埃氏筛从 p² 开始标记,处理 0、1 和上界不含 n。 | 题解 · 备用 |
| 080 | LC 172 · 阶乘后的零 | 精做 | 统计阶乘中质因子 5 的指数,不实际计算阶乘。 | 题解 · 备用 |
| 081 | LC 50 · Pow(x, n) | 精做 | 快速幂;先扩大指数类型再取负,处理最小 int。 | 题解 · 备用 |
| 082 | P1226 · 快速幂 | 精做 · 共享 | 模快速幂、乘法中间值和精确输出格式;不要用浮点 pow 代替。 | 对应方法 · 备用 |
| 083 | P3383 · 线性筛素数 | 选做 · 共享 | 线性筛模板的大规模实现;先算 n=10^8 的标记与素数表内存,再选择存储与 I/O。 | 对应方法 · 备用 |
过关标准: 能写欧几里得算法和模快速幂;能估计筛表内存;知道模运算不能随意做除法。
10 · 树、递归与子问题返回值 · 15 题
学习目标: 明确递归函数承诺返回什么;区分传入路径信息与汇总子树结果。
C++ 工具: TreeNode*、递归栈、queue、unordered_map;避免无意复制子数组。
阅读入口
- 做 144 前: 代码随想录:二叉树的递归遍历。看函数含义、终止条件、单层逻辑;尝试后再比较代码。
- 做 102 前: 代码随想录:二叉树的层序遍历。只读队列与按层分组的思路,先自己实现。
- 做 110 前: 代码随想录:二叉树理论基础。复查高度、深度与节点数;空树定义保持一致。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 084 | LC 144 · 二叉树的前序遍历 | 快练 | 前序递归,另用显式栈独立写一次。 | 题解 |
| 085 | LC 94 · 二叉树的中序遍历 | 快练 | 中序递归;练迭代版时解释当前指针与栈。 | 题解 |
| 086 | LC 145 · 二叉树的后序遍历 | 快练 | 后序访问顺序,理解汇总子树信息的时机。 | 题解 |
| 087 | LC 104 · 二叉树的最大深度 | 快练 | 返回子树高度;递归空间是 O(h)。 | 题解 |
| 088 | LC 226 · 翻转二叉树 | 快练 | 交换子树与空节点边界。 | 题解 |
| 089 | LC 101 · 对称二叉树 | 精做 | 成对比较镜像节点,参数含义决定递归配对。 | 题解 |
| 090 | LC 102 · 二叉树的层序遍历 | 精做 | 固定当前层节点数,避免与新入队节点混合。 | 题解 |
| 091 | LC 110 · 平衡二叉树 | 精做 | 一次后序返回高度或失败标记,避免反复计算高度。 | 题解 |
| 092 | LC 98 · 验证二叉搜索树 | 精做 | 约束来自全部祖先;仅比较父子不足以验证 BST。 | 题解 |
| 093 | LC 230 · 二叉搜索树中第 K 小的元素 | 快练 | 利用 BST 中序有序,得到第 k 个元素。 | 题解 |
| 094 | LC 112 · 路径总和 | 快练 | 必须到叶节点才检查路径和。 | 题解 · 备用 |
| 095 | LC 113 · 路径总和 II | 精做 | 收集路径并撤销修改,为回溯章作准备。 | 题解 · 备用 |
| 096 | LC 236 · 二叉树的最近公共祖先 | 精做 | 解释左右子树返回值如何决定最近公共祖先。 | 题解 |
| 097 | LC 543 · 二叉树的直径 | 精做 | 区分向父节点返回的单链高度与本节点经过两边的答案。 | 题解 |
| 098 | LC 105 · 从前序与中序遍历序列构造二叉树 | 精做 | 按中序位置划分左右子树,范围参数避免反复切片。 | 题解 |
过关标准: 能闭卷写一次迭代遍历;能把“高度/路径/整棵子树答案”分开定义,并用树高分析栈空间。
11 · 图遍历、BFS 与拓扑排序 · 10 题
学习目标: 把题面转成状态和边;区分遍历、无权最短路、依赖顺序。
C++ 工具: 邻接表、二维 visited、方向数组、queue;遍历前初始化状态。
阅读入口
- 做 733 前: 代码随想录:图论深搜理论基础。读搜索入口、边界、标记时机;回看图表示的邻接表即可。
- 做 994 前: 代码随想录:图论广搜理论基础。读多源入队与层数;理解相同边权下 BFS 的最短路性质。
- 做 207 前: 代码随想录:拓扑排序精讲(软件构建)。读入度、零入度队列、处理计数;注意边的方向由依赖语义决定。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 099 | LC 733 · 图像渲染 | 快练 | 洪水填充,原颜色等于新颜色时避免无限搜索。 | 题解 · 备用 |
| 100 | LC 200 · 岛屿数量 | 精做 | 连通块计数,已访问不能重复展开。 | 题解 |
| 101 | LC 695 · 岛屿的最大面积 | 快练 | 在连通块遍历中累计面积。 | 题解 |
| 102 | LC 994 · 腐烂的橘子 | 精做 | 多源 BFS 与分钟层次;检查最终仍未到达的节点。 | 题解 · 备用 |
| 103 | LC 1091 · 二进制矩阵中的最短路径 | 精做 | 八方向无权最短路,明确路径长度按格子数计算。 | 题解 · 备用 |
| 104 | LC 130 · 被围绕的区域 | 精做 | 从边界找保留区域,逆向思考被包围区域。 | 题解 · 备用 |
| 105 | LC 417 · 太平洋大西洋水流问题 | 选做 | 从海岸反向搜索,再取可达集合交集。 | 题解 · 备用 |
| 106 | LC 207 · 课程表 | 精做 | 有向依赖图建模与拓扑判环。 | 题解 |
| 107 | LC 210 · 课程表 II | 快练 | 从“存在顺序”迁移到“输出顺序”。 | 题解 · 备用 |
| 108 | LC 785 · 判断二分图 | 精做 | 用双色染色判断二分图,处理非连通图。 | 题解 · 备用 |
过关标准: 能说明何时标记 visited;比较网格和邻接表的成本;能通过处理节点数判断有向环。
12 · 搜索、回溯与剪枝 · 10 题
学习目标: 写清搜索树的一层代表什么、有哪些选择、何时撤销;从枚举升级到系统搜索。
C++ 工具: 递归传引用、push_back/pop_back、used、排序去重。
阅读入口
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 109 | LC 78 · 子集 | 精做 | 子集的选与不选,或者起点式枚举,先写熟一种。 | 题解 |
| 110 | LC 77 · 组合 | 快练 | 限定选择数量,并用剩余数量剪枝。 | 题解 |
| 111 | LC 46 · 全排列 | 精做 | 全排列使用 used,路径与选择空间分离。 | 题解 |
| 112 | LC 39 · 组合总和 | 精做 | 可重复选与起点控制;说明正数条件如何保证搜索终止。 | 题解 |
| 113 | LC 90 · 子集 II | 精做 | 重复元素子集,排序后进行同层去重。 | 题解 |
| 114 | LC 47 · 全排列 II | 精做 | 重复元素排列,解释 used 和前一个重复元素的关系。 | 题解 |
| 115 | LC 40 · 组合总和 II | 精做 | 每个元素只能用一次,结合和限制与同层去重。 | 题解 · 备用 |
| 116 | LC 79 · 单词搜索 | 精做 | 网格路径搜索,撤销 visited;与 200 的永久标记对照。 | 题解 · 备用 |
| 117 | LC 131 · 分割回文串 | 精做 | 枚举切割位置并判断回文,先不做 DP 预处理优化。 | 题解 · 备用 |
| 118 | LC 51 · N 皇后 | 选做 | 按行搜索,维护列和对角线约束;先写普通回溯。 | 题解 · 备用 |
过关标准: 能区分同层去重和同路径限制;从搜索树估计指数成本,而不是认为剪枝后一定很快。
13 · 并查集、最短路与最小生成树 · 8 题
学习目标: 掌握图算法的适用条件,独立实现并分析时间与空间复杂度。
C++ 工具: 邻接表、边结构体、小顶堆 pair、路径压缩、按大小合并、long long 距离。
阅读入口
- 做 P3367 前: 代码随想录:并查集理论基础。看集合代表、合并、路径压缩;同时使用按大小或按秩合并。
- 做 743 前: Dijkstra:朴素版。先看非负边条件与松弛;掌握朴素版的选择过程。
- 做 P4779 前: Dijkstra:堆优化。看堆优化、过期状态跳过与邻接表复杂度。
- 做 1584 前: 最小生成树:Prim。看最小生成树的割与每次加入的边;区别于累计路径距离。
- 做 P3366 前: 最小生成树:Kruskal。看边排序、并查集判环、选满 n-1 条边及非连通判断。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 119 | P3367 · 并查集 | 精做 · 共享 | 从零写并查集并处理完整输入,按题意输出 Y/N。 | 对应方法 |
| 120 | LC 684 · 冗余连接 | 精做 | 加边时检测已有连通性,找到形成环的边。 | 题解 |
| 121 | LC 547 · 省份数量 | 快练 | 把邻接矩阵转换为集合合并;也可对照 DFS。 | 题解 |
| 122 | LC 721 · 账户合并 | 选做 | 把相同邮箱映射到节点,连接后聚合和排序。 | 题解 · 备用 |
| 123 | LC 743 · 网络延迟时间 | 精做 | 非负边单源最短路,处理不可达节点。 | 题解 |
| 124 | P4779 · 单源最短路径(标准版) | 精做 · 共享 | 堆优化 Dijkstra 适应稀疏大图;不要默认 SPFA 能过所有数据。 | 对应方法 |
| 125 | LC 1584 · 连接所有点的最小费用 | 精做 | 隐含完全图优先试 O(n²) Prim,避免生成并排序全部边。 | 题解 |
| 126 | P3366 · 最小生成树 | 精做 · 共享 | 用 Kruskal 完成竞赛输入输出,非连通图输出题目指定结果。 | 对应方法 |
过关标准: 能区分 BFS、Dijkstra、Prim/Kruskal;最短路树和最小生成树的优化目标不同。
14 · 基础动态规划 · 11 题
学习目标: 从递归子问题得到记忆化与递推;状态定义必须先于转移代码。
C++ 工具: 一维二维 vector、初始化、无穷大哨兵、滚动变量;先正确再压缩空间。
阅读入口
- 做 70 前: 动态规划理论基础。只读状态、递推、初始化、遍历顺序;用小样例手算,不先背一串公式。
- 做 dp_a 前: 动态规划理论基础。回顾最优值型 DP 与方案数型 DP 的区别;自己从最后一步分类。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 127 | LC 70 · 爬楼梯 | 快练 | 从最后一步分类;画递归树看重复子问题。 | 题解 |
| 128 | LC 746 · 使用最小花费爬楼梯 | 精做 | 定义到达位置的最小代价,仔细处理起点和顶部。 | 题解 |
| 129 | DP A · Frog 1 | 精做 · 共享 | Frog 1:最后一步来源为前一或前二位置,完整输入输出。 | 对应方法 |
| 130 | DP B · Frog 2 | 精做 · 共享 | Frog 2:把两个来源推广为 K 个,推导 O(NK)。 | 对应方法 |
| 131 | LC 198 · 打家劫舍 | 精做 | 取当前房屋与不取两种选择,避免相邻。 | 题解 |
| 132 | LC 213 · 打家劫舍 II | 精做 | 环拆成两个线性范围,处理只有一间房。 | 题解 |
| 133 | DP C · Vacation | 精做 · 共享 | Vacation:状态增加上一次活动类别,不能重复选相邻类别。 | 对应方法 |
| 134 | LC 53 · 最大子数组和 | 精做 | 状态定义为“必须以当前位置结尾”,区别局部状态与全局答案。 | 题解 |
| 135 | LC 62 · 不同路径 | 快练 | 二维网格计数,明确首行首列边界。 | 题解 |
| 136 | LC 63 · 不同路径 II | 精做 | 障碍改变可达性,起点终点被挡与初始化。 | 题解 |
| 137 | LC 64 · 最小路径和 | 精做 | 从路径计数迁移到路径最小代价。 | 题解 · 备用 |
过关标准: 每题能写状态含义、转移来源、初始化、依赖顺序、时间空间复杂度。
15 · 背包、计数与状态设计 · 9 题
学习目标: 区分物品能用几次、求可行性/最优值/方案数,以及顺序是否造成新方案。
C++ 工具: 二维到一维压缩、倒序/正序依赖、计数整数范围。
阅读入口
- 做 dp_d 前: 01 背包:二维状态。先完整理解“前 i 件、容量 j”的二维模型,手填一张小表。
- 完成 dp_d 后、做 416 前: 01 背包:一维压缩。再压成一维;解释读的是上一层还是本层,不只记倒序。
- 做 322 前: 完全背包:二维状态。理解物品可重复使用,再看一维容量正序。
- 做 518、377 前: 完全背包:一维压缩。用 1、2 凑 3 手算,区分组合和排列的循环顺序。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 138 | DP D · Knapsack 1 | 精做 · 共享 | 标准 0/1 背包,先二维后压缩;估算价值总和的整数范围。 | 对应方法 |
| 139 | LC 416 · 分割等和子集 | 精做 | 把等和划分转化为恰好达到总和一半的可行性。 | 题解 |
| 140 | LC 494 · 目标和 | 精做 | 符号选择转化为子集和计数;零元素与无解条件。 | 题解 · 备用 |
| 141 | LC 474 · 一和零 | 选做 | 两个容量维度的 0/1 背包,两个容量都要倒序。 | 题解 · 备用 |
| 142 | LC 322 · 零钱兑换 | 精做 | 完全背包求最少硬币,区分不可达与零枚硬币。 | 题解 |
| 143 | LC 518 · 零钱兑换 II | 精做 | 完全背包数无序组合,空方案初始化。 | 题解 |
| 144 | LC 377 · 组合总和 Ⅳ | 精做 | 顺序不同算不同方案,改变循环含义;注意中间计数范围。 | 题解 · 备用 |
| 145 | LC 139 · 单词拆分 | 精做 | 前缀能否拆分,枚举最后一个词;计入子串构造成本。 | 题解 · 备用 |
| 146 | DP E · Knapsack 2 | 选做 · 共享 | 容量太大时按总价值定义最小重量,练习重新设计状态。 | 对应方法 |
过关标准: 能解释 0/1 背包倒序的来源;能用小样例区分 518 的组合与 377 的排列。
16 · 子序列、区间与树形 DP · 7 题
学习目标: 由序列状态扩大到双序列、区间和树;先完成基础三题再决定是否深入。
C++ 工具: 二维表、路径恢复、后序遍历、模数计算;大深度树注意递归栈。
阅读入口
- 尝试 300 后: 300 最长递增子序列:对应讲解。第一次先做 O(n²) DP;尝试后再读题解。O(n log n) 优化可留第二轮。
- 做 516、dp_n 前: OI Wiki:区间 DP · 官网。只在进入选做题时读:区间端点、分割点、按长度递增的顺序。
- 做 dp_p 前: OI Wiki:树形 DP · 官网。只读树上父子状态依赖,结合第 10 章后序汇总;先不读换根 DP。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 147 | LC 300 · 最长递增子序列 | 精做 | 以 i 结尾的 LIS,先理解 O(n²) 转移,再考虑二分优化。 | 题解 |
| 148 | LC 1143 · 最长公共子序列 | 精做 | 两个前缀的 LCS 长度,推导相等与不等时的来源。 | 题解 |
| 149 | DP F · LCS | 精做 · 共享 | 输出 LCS 本身,沿 DP 表恢复一个合法最优序列。 | 对应方法 |
| 150 | LC 72 · 编辑距离 | 精做 | 插入、删除、替换对应哪些子问题;初始化空字符串。 | 题解 · 备用 |
| 151 | LC 516 · 最长回文子序列 | 选做 | 区间两端是否匹配决定最长回文子序列。 | 题解 · 备用 |
| 152 | DP N · Slimes | 选做 · 共享 | Slimes:枚举最后合并的分割点,前缀和求区间代价;先用 O(n³)。 | 对应方法 · 备用 |
| 153 | DP P · Independent Set | 选做 · 共享 | Independent Set:定义节点黑/白状态,组合子树方案并取模。 | 对应方法 · 备用 |
过关标准: 能区分子数组与子序列;能恢复一条 LCS;进阶时能按区间长度或树的依赖顺序计算。
17 · KMP 与字典树 · 3 题
学习目标: 理解 KMP 与前缀函数,利用字符串前缀信息减少重复工作。
C++ 工具: string、前缀函数、数组型 Trie 节点与终止标记。
阅读入口
- 做 28 前: KMP 与前缀表。先学前后缀、失配回退;固定一种前缀函数定义,区分不同 next 数组约定。
- 做 208 前: OI Wiki:字典树 · 官网。只读插入、查询、前缀查询;暂不读可持久化 Trie 或异或 Trie。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 154 | LC 28 · 找出字符串中第一个匹配项的下标 | 精做 | 先明白朴素匹配,再独立实现 KMP;本题不用 find 代替训练。 | 题解 |
| 155 | P3375 · KMP | 精做 · 共享 | 输出所有匹配位置及前缀函数,处理重叠匹配与下标转换。 | 对应方法 |
| 156 | LC 208 · 实现 Trie(前缀树) | 选做 | 实现 Trie 插入、完整查询和前缀查询,处理重复插入。 | 题解 · 备用 |
过关标准: 能手推重复字符样例的前缀函数;区分 Trie 中完整单词和仅为前缀。
18 · 树状数组与线段树 · 4 题
学习目标: 竞赛扩展章:静态前缀和不能处理频繁修改时,学习动态区间查询。
C++ 工具: lowbit、1-based 下标、long long、递归区间与懒标记。
阅读入口
- 做 P3374 前: OI Wiki:树状数组 · 官网。只读单点加与前缀和,用 1 到 8 的下标手画覆盖关系。
- 做 P3368 前: OI Wiki:树状数组 · 官网。回看第 4 章差分,再学习区间加、单点查。
- 做 P3372 前: OI Wiki:线段树基础 · 官网。只读建树、区间和、区间加、懒标记;进阶内容按需扩展。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 157 | P3374 · 树状数组 1 | 选做 · 共享 | 树状数组单点加、区间和;写出两个 lowbit 循环的含义。 | 对应方法 · 备用 |
| 158 | LC 307 · 区域和检索 - 数组可修改 | 选做 | 将“修改成 val”转为增量,复用树状数组;也可第二轮用线段树。 | 方法 · 备用 |
| 159 | P3368 · 树状数组 2 | 选做 · 共享 | 差分加树状数组,实现区间加与单点查。 | 对应方法 · 备用 |
| 160 | P3372 · 线段树 1 | 选做 · 共享 | 线段树区间加与区间求和,正确传递懒标记并使用 long long。 | 对应方法 · 备用 |
过关标准: 能说明树状数组每个节点覆盖的区间;能区分修改为新值与增加 delta。
围绕标准输入输出、竞赛建模与综合应用训练。40 道 AtCoder、40 道洛谷,其中 22 道与算法主线共享。
| 章节 | 内容 | 题量 |
|---|---|---|
| 01 | 完整程序与模拟 | 8 |
| 02 | 枚举与数学观察 | 7 |
| 03 | 排序、计数与贪心 | 7 |
| 04 | 前缀和、差分与窗口 | 7 |
| 05 | 二分查找与二分答案 | 5 |
| 06 | 栈、队列与堆 | 4 |
| 07 | 搜索、回溯与图遍历 | 6 |
| 08 | 基础数学、素数与模运算 | 6 |
| 09 | 基础 DP、背包与序列 | 9 |
| 10 | 图算法、树上累加与依赖关系 | 7 |
| 11 | 蓝桥真题与综合应用 | 6 |
| 12 | 后续扩展:全部选做 | 8 |
01 · 完整程序与模拟 · 8 题
学习目标: 输入协议 → 状态变量 → 状态更新 → 输出时机;独立完成编译、运行和提交。
C++ 工具: main、cin/cout、string、vector;多组状态重置,按题意读到终止标记。
阅读入口
- 进入本章: C++ 起步与使用说明。先读竞赛输入输出部分;基础语法已会的部分略过。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 001 | PracticeA · Welcome to AtCoder | 快练 · 共享 | 独立写完整程序,走通编译、运行、提交 | 对应方法 · 备用 |
| 002 | ABC284 B · Multi Test Cases | 快练 | T 组输入、每组计数重置、逐组输出 | — |
| 003 | ABC081 B · Shift only | 快练 | 数组整体模拟、停止条件、循环次数估计 | — |
| 004 | ABC332 B · Glass and Mug | 主练 | 按优先级执行动作,正确更新两个容器的状态 | — |
| 005 | ABC293 B · Call the ID Number | 主练 | 顺序处理和标记数组,构造并输出结果集合 | — |
| 006 | P5734 · 文字处理软件 | 主练 | string 操作、不同操作的读入、查找失败与下标 | — |
| 007 | P1042 · 乒乓球 | 主练 | 跨行读字符、E 终止、两套计分、局末及 0:0 边界 | — |
| 008 | P1563 · 玩具谜题 | 选做 | 圆环方向、负数取模,把文字规则写成确定的状态变化 | — |
过关标准: 能从空文件完成程序;能解释首个整数的含义、何时初始化和何时输出。完成本章主练就可进入后面的 CF 桥接,不必等 008。
02 · 枚举与数学观察 · 7 题
学习目标: 先确定枚举对象与范围,再估算总成本;利用约束减少自由变量。
C++ 工具: 整数除法与取模、long long;选做再补位运算与 next_permutation。
阅读入口
- 011 前阅读: OI Wiki:枚举。先确定枚举对象与范围,再估算总成本;利用约束减少自由变量。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 009 | ABC083B · Some Sums | 快练 · 共享 | 枚举整数、拆分数位、区分取模和整除 | 对应方法 · 备用 |
| 010 | ABC087 B · Coins | 快练 | 依据小范围选择暴力,估计实际循环上界 | — |
| 011 | ABC085C · Otoshidama | 主练 · 共享 | 数量约束降维,找任意解,处理无解 | 对应方法 · 备用 |
| 012 | ABC086C · Traveling | 主练 · 共享 | 用距离与奇偶性代替逐步模拟;说明可达条件的充分性 | 对应方法 · 备用 |
| 013 | ABC338 C · Leftover Recipes | 主练 | 枚举一种选择,再由各项资源限制另一种选择;防止除零 | — |
| 014 | ABC128 C · Switches | 选做 | 二进制表示选择集合,认识 2^n 枚举的适用规模 | — |
| 015 | ABC150 C · Count Order | 选做 | next_permutation、全排列与阶乘复杂度 | — |
过关标准: 写循环前能估计总操作量;能区分“一个可行解”和“所有方案数”。012 不只背两个判断式,要解释为什么它们足够。
03 · 排序、计数与贪心 · 7 题
学习目标: 用排序安排处理顺序,用计数保留重复信息,并说明贪心选择为什么安全。
C++ 工具: sort、比较器、map、频次数组;计数结果和累加量检查 64 位范围。
阅读入口
- 按需查阅主线第 2 章资料: 哈希表理论基础。看数组、set、map 各适合记录什么;只读 C++,暂不深挖哈希表源码。
- 按需查阅主线第 8 章资料: Hello 算法:快速排序 · 官网。看划分、递归边界、退化情况;理解三数取中,但不混用不同 partition 约定。
- 按需查阅主线第 8 章资料: 贪心算法理论基础。看局部最优与整体最优的联系,避免“感觉可行”当证明。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 016 | P1059 · 明明的随机数 | 快练 | 排序去重、有效长度与结果输出 | — |
| 017 | ABC088 B · Card Game for Two | 快练 | 排序后的轮流选择,解释选择大数的理由 | — |
| 018 | ABC137 C · Green Bin | 主练 | 为同类字符串设计共同表示,再计数配对 | — |
| 019 | ABC159 D · Banned K | 主练 | 从总方案数计算删除一个元素的影响,答案用足够宽的整数 | — |
| 020 | ABC176 C · Step | 主练 | 维护前缀约束,以最小修改推进;累加值的范围 | — |
| 021 | P1223 · 排队接水 | 主练 | 排序贪心、相同时间按编号;平均等待时间与两位小数输出 | — |
| 022 | P1803 · 凌乱的yyy/线段覆盖 | 主练 | 区间选择,说明按结束时间选择的依据及端点条件 | — |
过关标准: 能对一个错误的排序策略给反例;能说明重复元素按“值”还是按“位置”计数。到这里应已尝试过 CF 桥接和一次陌生题限时练习。
04 · 前缀和、差分与窗口 · 7 题
学习目标: 区分静态区间查询、批量区间修改与窗口维护;推导端点和下标公式。
C++ 工具: 前缀/差分数组、半开区间、双指针;数据量较大时先核算内存。
阅读入口
- 进入本章,按需读: OI Wiki:前缀和与差分。区分静态区间查询、批量区间修改与窗口维护;推导端点和下标公式。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 023 | P8218 · 求区间和 | 快练 | 前缀和与闭区间查询;按 n、数组、m、查询的顺序读入 | — |
| 024 | ABC122 C · GeT AC | 主练 | 把相邻字符对变成前缀计数,处理查询左端边界 | — |
| 025 | P1614 · 爱与愁的心痛 | 快练 | 用 O(n) 固定窗口迁移已学双指针;检查题面允许的 m=0 | — |
| 026 | ABC229 D · Longest X | 主练 | 把可修改次数变成窗口限制,解释左右指针如何移动 | — |
| 027 | ABC183 D · Water Heater | 主练 | 半开时间区间差分、端点同时发生事件、64 位累加 | — |
| 028 | P2367 · 语文成绩 | 选做 | 大规模一维差分;只在全部修改后求最小值,核算内存和读入成本 | — |
| 029 | P3397 · 地毯 | 主练 · 共享 | 二维差分、四角更新、还原覆盖次数 | 对应方法 · 备用 |
过关标准: 能从头推导区间公式,而不是只记下标;能解释静态前缀和为什么不适合直接处理交错的修改和查询。
05 · 二分查找与二分答案 · 5 题
学习目标: 先定义可行性条件并证明单调性,再选查找边界与区间不变量。
C++ 工具: lower_bound、边界约定、单调 check;复杂度计入一次判定的成本。
阅读入口
- 进入本章,按需读: OI Wiki:二分。先定义可行性条件并证明单调性,再选查找边界与区间不变量。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 030 | P2249 · 查找 | 主练 | 第一次出现的位置,未找到、全部相同与 1-based 输出 | — |
| 031 | ABC231 C · Counting 2 | 主练 | 排序后回答大量阈值查询,找边界后换算数量 | — |
| 032 | ABC146 C · Buy an Integer | 主练 | 单调成本下求最大可行值,处理 0、上限与数位变化 | — |
| 033 | P8647 · [蓝桥杯 2017 省 AB] 分巧克力 | 主练 | 由答案构造可行性判定;块数的乘积与总和用 64 位 | — |
| 034 | P2678 · 跳石头 | 选做 | 二分结合贪心检验,额外说明为什么判定过程正确 | — |
过关标准: 空间中不存在可行值、答案在端点、判定恰好相等时仍能写对;复杂度包含一次 check 的成本。
06 · 栈、队列与堆 · 4 题
学习目标: 栈处理最近未完成项,队列维护先后,堆维护动态极值;区分算法理由与容器作用。
C++ 工具: stack、queue、priority_queue;小根堆配置与表达式操作数顺序。
阅读入口
- 按需查阅主线第 7 章资料: 栈与队列理论基础。看容器接口与栈/队列行为,不必手写所有底层实现。
- 按需查阅主线第 7 章资料: Hello 算法:堆。看大小顶堆、插入删除、建堆和 C++ priority_queue 用法。
- 按需查阅主线第 7 章资料: 代码随想录:每日温度中的单调栈入门。只读“单调栈适用什么问题”和栈存下标的意义;不提前读 739 的完整代码。
- 按需查阅主线第 7 章资料: NeetCode:前K个高频元素的堆法与频率分桶。堆法先理解;再读频率桶,解释哈希统计加桶为什么平均 O(n)。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 035 | P1449 · 后缀表达式 | 主练 | 多位数解析、数字与表达式终止符、减法/除法的操作数顺序 | — |
| 036 | P1540 · 机器翻译 | 主练 | 队列和存在标记共同维护缓存,命中时按题目规则处理 | — |
| 037 | P3378 · 堆 | 快练 | priority_queue 配成小根堆,读取不同参数个数的操作 | — |
| 038 | P1090 · 合并果子 | 主练 | 动态选择最小两项,联系哈夫曼树,解释贪心与堆各自的作用 | — |
过关标准: 能区分“证明为什么选它”和“用什么容器高效找到它”;能估计整个操作序列的成本。
07 · 搜索、回溯与图遍历 · 6 题
学习目标: 定义搜索状态、可选动作与终止条件;区分路径内撤销和遍历的永久标记。
C++ 工具: 递归与撤销、方向数组、邻接表、queue;明确 visited 的作用范围。
阅读入口
- 039 前读基本框架: OI Wiki:DFS。定义搜索状态、可选动作与终止条件;区分路径内撤销和遍历的永久标记。
- 按需查阅主线第 11 章资料: 代码随想录:图论深搜理论基础。读搜索入口、边界、标记时机;回看图表示的邻接表即可。
- 按需查阅主线第 11 章资料: 代码随想录:图论广搜理论基础。读多源入队与层数;理解相同边权下 BFS 的最短路性质。
- 按需查阅主线第 11 章资料: 代码随想录:拓扑排序精讲(软件构建)。读入度、零入度队列、处理计数;注意边的方向由依赖语义决定。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 039 | P1706 · 全排列问题 | 主练 | 本次用回溯实现,维护已用数字并撤销;题目要求每个数字 5 个场宽 | — |
| 040 | ABC293 C · Make Takahashi Happy | 主练 | 枚举网格路径,限制路径上的数值不重复,正确恢复现场 | — |
| 041 | P1219 · 八皇后 | 选做 | 列和对角线约束、剪枝、前三解与总方案数 | — |
| 042 | P1162 · 填涂颜色 | 主练 | 从外部区域建模,区分连通的外部与被包围区域 | — |
| 043 | P1443 · 马的遍历 | 主练 | BFS 最短步数、方向数组、不可达 -1;现题面无需固定输出场宽 | — |
| 044 | ABC284 C · Count Connected Components | 主练 | 从边表独立建邻接表,遍历非连通图并覆盖孤立点 | — |
过关标准: 能解释何时回溯撤销、何时永久标记;BFS 能说明为什么首次到达就是最少步数。040 是路径枚举,不能套普通 flood fill 的永久标记。
08 · 基础数学、素数与模运算 · 6 题
学习目标: 串起 gcd/lcm、约数、素数、快速幂与模运算;从循环推导复杂度并检查整数边界。
C++ 工具: gcd、整数范围与模减法;乘法运算前提升类型。
阅读入口
- 按需查阅主线第 9 章资料: OI Wiki:位操作 · 官网。只看异或、移位、清除最低位 1;暂不读高级二进制技巧。
- 按需查阅主线第 9 章资料: OI Wiki:最大公约数 · 官网。看欧几里得算法及 gcd 与 lcm;扩展欧几里得留到后续专题。
- 按需查阅主线第 9 章资料: OI Wiki:筛法 · 官网。先读埃氏筛;只有做 P3383 时再读线性筛与大规模空间开销。
- 按需查阅主线第 9 章资料: OI Wiki:快速幂 · 官网。读按二进制拆指数与迭代快速幂;做 P1226 时加入取模。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 045 | ABC148 C · Snack | 快练 | gcd/lcm 建模、先除后乘及结果的整数范围 | — |
| 046 | ABC180 C · Cream puff | 主练 | 在平方根范围枚举约数,完全平方数去重、排序输出 | — |
| 047 | P5723 · 质数口袋 | 快练 | 先用试除判素,再用埃氏筛对照;处理 1、预算不足与停止时机 | — |
| 048 | P1226 · 快速幂 | 主练 · 共享 | 推导二进制幂;按题面输出 a^b mod p=s,不能只打印数值 | 对应方法 · 备用 |
| 049 | ABC177 C · Sum of product of pairs | 主练 | 把两两乘积求和降为线性计算,处理乘法与取模 | — |
| 050 | ABC178 C · Ubiquity | 选做 | 容斥与幂计数;先解释集合关系,再处理模减法 | — |
过关标准: 解释 O(√n)、O(log k) 从哪里来;知道最后赋给 long long 无法修复此前已发生的 int 溢出。线性筛大数据题放在 077,不作为开始参赛的条件。
09 · 基础 DP、背包与序列 · 9 题
学习目标: 状态含义 → 最后一步或最后一次选择 → 转移 → 初始化 → 计算顺序,再解释空间压缩。
C++ 工具: 二维状态、一维压缩、long long、路径/方案恢复。
阅读入口
- 055 前读 0/1 背包;057 前读完全背包: OI Wiki:背包 DP。状态含义 → 最后一步或最后一次选择 → 转移 → 初始化 → 计算顺序,再解释空间压缩。
- 按需查阅主线第 14 章资料: 动态规划理论基础。只读状态、递推、初始化、遍历顺序;用小样例手算,不先背一串公式。
- 按需查阅主线第 16 章资料: 300 最长递增子序列:对应讲解。第一次先做 O(n²) DP;尝试后再读题解。O(n log n) 优化可留第二轮。
- 按需查阅主线第 16 章资料: OI Wiki:区间 DP · 官网。只在进入选做题时读:区间端点、分割点、按长度递增的顺序。
- 按需查阅主线第 16 章资料: OI Wiki:树形 DP · 官网。只读树上父子状态依赖,结合第 10 章后序汇总;先不读换根 DP。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 051 | DP A · Frog 1 | 主练 · 共享 | 从最后一步定义状态、递推和初值 | 对应方法 |
| 052 | DP B · Frog 2 | 快练 · 共享 | 从固定两个来源扩展到 K 个,推导 O(NK) | 对应方法 |
| 053 | DP C · Vacation | 主练 · 共享 | 为相邻选择的限制增加状态,保存必要历史 | 对应方法 |
| 054 | DP H · Grid 1 | 主练 | 障碍网格计数、起点初始化与取模 | — |
| 055 | P1048 · 采药 | 主练 | 0/1 背包,独立写出二维状态再压缩 | — |
| 056 | DP D · Knapsack 1 | 主练 · 共享 | 将背包迁移到更大的数值范围,检查价值总和;共享题不重做 | 对应方法 |
| 057 | P1616 · 疯狂的采药 | 主练 | 完全背包,与 055 比较更新顺序;检查 m×t 约束,dp 用 64 位 | — |
| 058 | DP E · Knapsack 2 | 选做 · 共享 | 由数据范围判断原状态不可行,改按价值定义最小重量 | 对应方法 |
| 059 | DP F · LCS | 主练 · 共享 | 双序列 DP,并恢复一个实际子序列;需要输出字符串 | 对应方法 |
过关标准: 每题先写一句状态定义;能解释初始化和循环顺序。完成 055 后,056 作为迁移校验,不再重复看一整套背包课;059 的恢复部分可以拆成第二次练习。
10 · 图算法、树上累加与依赖关系 · 7 题
学习目标: 从方向、权重和目标选择 BFS、并查集、Dijkstra、最小生成树或拓扑排序。
C++ 工具: 邻接表、入度队列、堆、并查集;长链考虑迭代遍历。
阅读入口
- 按需查阅主线第 13 章资料: 代码随想录:并查集理论基础。看集合代表、合并、路径压缩;同时使用按大小或按秩合并。
- 按需查阅主线第 13 章资料: Dijkstra:朴素版。先看非负边条件与松弛;掌握朴素版的选择过程。
- 按需查阅主线第 13 章资料: Dijkstra:堆优化。看堆优化、过期状态跳过与邻接表复杂度。
- 按需查阅主线第 13 章资料: 最小生成树:Prim。看最小生成树的割与每次加入的边;区别于累计路径距离。
- 按需查阅主线第 13 章资料: 最小生成树:Kruskal。看边排序、并查集判环、选满 n-1 条边及非连通判断。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 060 | P3367 · 并查集 | 主练 · 共享 | 合并与查找、路径压缩、按要求输出 Y/N | 对应方法 |
| 061 | ABC168 D · .. (Double Dots) | 主练 | BFS 记录前驱,输出一种合法路径树,理解答案可以不唯一 | — |
| 062 | ABC138 D · Ki | 主练 | 树上更新汇总后传播,明确父子方向;长链考虑迭代遍历 | — |
| 063 | P4779 · 单源最短路径(标准版) | 主练 · 共享 | 邻接表、堆优化 Dijkstra、过期堆元素与距离类型 | 对应方法 |
| 064 | P3366 · 最小生成树 | 主练 · 共享 | Kruskal 与并查集,检查不连通时输出 orz | 对应方法 |
| 065 | P1113 · 杂务 | 主练 | 每行依赖列表以 0 结束;已有依赖顺序下计算最早完成时间 | — |
| 066 | DP G · Longest Path | 主练 | 本次用入度队列求拓扑序,再在 DAG 上做最长路 DP | — |
过关标准: 能比较邻接矩阵与邻接表成本,说明 Dijkstra 的适用条件,以及最短路与最小生成树的目标差异。065 已保证前置任务编号更小,不能用它代替一般拓扑排序的实现检验;066 承担这一任务。
11 · 蓝桥真题与综合应用 · 6 题
学习目标: 先遮住训练重点,由题面和约束独立建立模型;用蓝桥真题检验算法迁移。
C++ 工具: 复用已学容器和算法;从约束检查中间值范围与可行复杂度。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 067 | P8780 · [蓝桥杯 2022 省 B] 刷题统计 | 主练 | 周期计算与余量处理,不能逐天模拟到 10^18;先检查中间值范围。第 2 章后已有前置 | — |
| 068 | P8707 · [蓝桥杯 2020 省 AB1] 走方格 | 快练 | 从文字规则确定禁入格,检验网格 DP 迁移;第 9 章后做 | — |
| 069 | P9240 · [蓝桥杯 2023 省 B] 冶炼金属 | 主练 | 整除不等式、上下界与多个条件的交集;第 8 章后已有前置 | — |
| 070 | P9242 · [蓝桥杯 2023 省 B] 接龙数列 | 主练 | 利用小值域设计状态,避免直接枚举所有前驱;第 9 章后做 | — |
| 071 | P1083 · 借教室 | 选做 | 差分+二分的综合,检查每次判定的重置、大输入与数值范围 | — |
| 072 | ABC305 D · Sleep Log | 选做 | 二分+前缀统计,处理查询端点落在区间内部 | — |
过关标准: 面对陌生题面,先写出数学或状态模型,再选择算法;用未做过的整套真题检验建模、实现与时间分配。
12 · 后续扩展:全部选做 · 8 题
学习目标: 全部选做,每次只补一个真实缺口;KMP、动态区间查询与进阶 DP 不作为开始参赛的条件。
C++ 工具: 按缺口补前缀函数、lowbit、懒标记、区间/树形状态。
阅读入口
- 按需查阅主线第 17 章资料: KMP 与前缀表。先学前后缀、失配回退;固定一种前缀函数定义,区分不同 next 数组约定。
- 按需查阅主线第 17 章资料: OI Wiki:字典树 · 官网。只读插入、查询、前缀查询;暂不读可持久化 Trie 或异或 Trie。
- 按需查阅主线第 18 章资料: OI Wiki:树状数组 · 官网。只读单点加与前缀和,用 1 到 8 的下标手画覆盖关系。
- 按需查阅主线第 18 章资料: OI Wiki:线段树基础 · 官网。只读建树、区间和、区间加、懒标记;进阶内容按需扩展。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 073 | P3375 · KMP | 选做 · 共享 | 前缀函数、重叠匹配、匹配位置与前缀信息输出 | 对应方法 |
| 074 | P3374 · 树状数组 1 | 选做 · 共享 | 单点加、区间和;先解释静态前缀和的限制与 lowbit | 对应方法 · 备用 |
| 075 | P3368 · 树状数组 2 | 选做 · 共享 | 差分与树状数组结合,区间加、单点查;先做 074 | 对应方法 · 备用 |
| 076 | P3372 · 线段树 1 | 选做 · 共享 | 区间加与区间和、懒标记和 64 位维护 | 对应方法 · 备用 |
| 077 | P3383 · 线性筛素数 | 选做 · 共享 | 第 k 小素数查询;当前 n=10^8,先估标记和素数表的内存,再写代码 | 对应方法 · 备用 |
| 078 | DP N · Slimes | 选做 · 共享 | 区间 DP 与 O(n³) 转移;与 038 比较“必须相邻合并”的影响 | 对应方法 · 备用 |
| 079 | DP P · Independent Set | 选做 · 共享 | 树上黑白状态、合并子树方案与取模;先掌握树遍历和基础 DP | 对应方法 · 备用 |
| 080 | P1719 · 最大加权矩形 | 选做 | 二维问题降为一维最大子段和,推导 O(n³),处理全负数 | — |
过关标准: 选做按实际缺口选择;先能解释状态、适用条件与复杂度,再独立实现和检查边界。
从完整程序与简单题开始,逐步练习计数、排序、构造与区间应用。具备基础能力后即可尝试整场练习。
| 章节 | 内容 | 题量 |
|---|---|---|
| 01 | 完整程序与入门桥接 | 6 |
| 02 | 字符串、计数与排序 | 6 |
| 03 | 构造、数学观察与区间 | 6 |
01 · 完整程序与入门桥接 · 6 题
学习目标: 前两题快速熟悉提交,再练多组输入、字符串和简单排序。完成这 6 题即可尝试入门赛。
C++ 工具: main、cin/cout、string、sort;逐题确认测试组数与输出格式。
阅读入口
- 本阶段学习要点: Codeforces 官方题库。前两题能独立完成就快过;05、06 前补竞赛补充第 3 章的排序与计数。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 01 | CF 4A · Watermelon | 快练 | 熟悉提交与边界 | — |
| 02 | CF 282A · Bit++ | 快练 | 简单字符串读入与操作模拟 | — |
| 03 | CF 1328A · Divisibility Problem | 主练 | T 组输入与整数观察 | — |
| 04 | CF 71A · Way Too Long Words | 主练 | 字符串边界与批量输出 | — |
| 05 | CF 339A · Helpful Maths | 主练 | 解析、排序/计数与分隔符输出 | — |
| 06 | CF 160A · Twins | 主练 | 排序贪心与严格不等式 | — |
过关标准: 能独立读题、提交完整程序并定位基本错误;不必等后两章完成才参赛。
02 · 字符串、计数与排序 · 6 题
学习目标: 把相邻关系、覆盖集合、位置条件和排序后的窗口转成可维护的信息。
C++ 工具: 频次数组、布尔标记、string::substr、map、sort;明确下标和重复计数。
阅读入口
- 本阶段学习要点: Codeforces 官方题库。衔接竞赛补充第 2–4 章;每道题先自己确定应保留哪些信息。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 07 | CF 266A · Stones on the Table | 主练 | 相邻字符关系、连续重复与最少删除次数 | — |
| 08 | CF 469A · I Wanna Be the Guy | 主练 | 集合覆盖与去重;读入两组不同长度的数据 | — |
| 09 | CF 1367B · Even Array | 主练 | 区分下标和数值的奇偶性,统计错位并判断能否修复 | — |
| 10 | CF 977B · Two-gram | 主练 | 长度为 2 的子串计数,允许重叠,输出出现最多的一种 | — |
| 11 | CF 405A · Gravity Flip | 主练 | 从模拟描述识别排序模型,解释最终状态 | — |
| 12 | CF 337A · Puzzles | 主练 | 排序后枚举固定长度区间,最小化最大值与最小值之差 | — |
过关标准: 能区分按位置计数与按值去重,解释排序如何帮助求解,并检查全相同、缺失和边界位置。
03 · 构造、数学观察与区间 · 6 题
学习目标: 先推导必要条件,再验证构造或枚举是否充分;逐步迁移到窗口与二分查询。
C++ 工具: long long、取模和整除、排序、前缀和/滑动窗口、upper_bound。
阅读入口
- 本阶段学习要点: Codeforces 官方题库。先会基础枚举与排序;最后两题结合竞赛补充第 4–5 章做。卡住可以先参加前段简单题训练。
| # | 题目 | 投入 | 训练重点 | 参考 |
|---|---|---|---|---|
| 13 | CF 1343B · Balanced Array | 主练 | 推导可行性条件;构造等和数组并满足正数、互异等约束 | — |
| 14 | CF 1512B · Almost Rectangle | 主练 | 按两点的位置分类构造矩形,处理同一行/列与多组输入 | — |
| 15 | CF 1374B · Multiply by 2, divide by 6 | 主练 | 从操作推导整数因子的限制,判断可达性并计算最少次数 | — |
| 16 | CF 1360C · Similar Pairs | 主练 | 奇偶分类与配对条件,解释何时需要利用相差 1 的数对 | — |
| 17 | CF 363B · Fence | 主练 | 固定长度窗口/前缀和,线性求最小区间和并返回位置 | — |
| 18 | CF 706B · Interesting drink | 主练 | 排序+upper_bound 回答多次阈值计数,处理重复值与恰好相等 | — |
过关标准: 构造题能验证全部条件;能从数据规模发现逐次扫描不可行,并说明窗口或二分为何有效。
选择尚未读过题面和题解的场次,先独立选题、限时实现,再补最接近当前能力的题。做过的场次更适合复盘,不再作为陌生题测试。
| 场次 | 使用方式 |
|---|---|
| Codeforces Round 964 · Div. 4 | 从 A–C 开始;整场 145 分钟,首次练习可略过后段交互题 |
| AtCoder Beginner Contest 350 | 先尝试 A、B,再看 C;练习时隐藏算法标签 |
虚拟赛不产生正式 rating。正式比赛的时间、规则与参赛条件以官方公告为准:Codeforces 比赛列表 · AtCoder 比赛列表。
题目、题解与教程链接指向各自的平台和作者;本仓库整理学习顺序与训练重点,不复制完整题面或外部题解。
- 评测平台:LeetCode · AtCoder · 洛谷 · Codeforces
- 基础资料:OI Wiki · Hello 算法
- 题解参考:代码随想录 · Doocs LeetCode · NeetCode
章节内的链接已细化到具体资料。建议先读定义与思路,再按需要阅读代码;外部页面可能包含完整答案。
题单数据位于 data/roadmap.json,网页模板位于 src/template.html。修改后使用 Node.js 18 或更高版本,在仓库目录执行:
node scripts/build.mjs脚本会检查题目编号与路线数量,并重新生成 README.md 和 index.html;不需要第三方依赖。阅读题单和打开网页无需 Node.js。
欢迎通过 Issue 或 Pull Request 修正失效链接、题目描述和练习顺序。提交时请只包含通用资料,不要附带浏览器进度、个人笔记或本地配置。
本仓库原创文档与代码采用 MIT License。外部链接指向的题目、教程和题解遵循原平台或作者的许可。