news 2026/10/7 1:12:43

CSP-J复试全拆解:四题考点、工程避坑与分数最大化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CSP-J复试全拆解:四题考点、工程避坑与分数最大化

1. 复试不是初赛的加长版,它考的是另一种能力

很多人对 CSP-J 的认知停在第一轮:选择题、判断题、读程序写结果,背背语法,刷几套卷子就能过。但真正决定你能不能拿到"入门级一等奖"或者被高中教练看上的,是第二轮——也就是我们常说的复试、复赛。它跟初赛几乎是两门完全不同的考试,初赛考的是"你对语言和基础概念的熟悉程度",复试考的是"你能不能在一台只有编译器的机器上,从一张白纸开始,把一个问题拆开、写成代码、让它在限定时间内跑出正确答案"。

我见过太多初赛分数很高的同学,第一次进复试就懵了:四道题,210 分钟,题面有三四页,样例过了一交上去就是 0 分。问题往往不在"算法不会",而在于对整个复试考点的分布、评分方式、代码工程细节完全没有概念。这篇文章我想做的,就是把 CSP-J 复试这件事拆开讲透——它到底考什么、每类考点该怎么准备、哪些地方最容易无谓丢分、以及怎么用有限的备考时间把分数最大化。不管你是刚过初赛的初一学生,还是带学生打比赛的教练,这篇内容都能直接拿去用。

说明:CSP-J 第二轮的题量、时长、文件输入输出要求,以当年 CCF 官方发布的考试说明和题目 PDF 为准。下面讲的考点分布和备考方法,来自我个人的带练与复盘经验,属于"常见实践"层面的总结,不是官方标准。

1.1 从"选一个答案"到"从零构造一个解"

初赛和复试最本质的差别,是"信息量"的方向反了过来。初赛给你一段代码,让你推结果;复试给你一个场景和一堆约束,让你倒着设计出代码。这个过程里,考的其实是三件事:

  • 建模能力:能不能把中文题面翻译成"输入是什么、输出是什么、中间要维护哪些状态"。
  • 检索能力:看到"求最大值最小""n 最大到 10^5""多次区间修改",脑子里要能自动匹配出对应的算法模板。
  • 工程能力:模板写出来了,变量类型对不对、数组开没开够、文件读写有没有按题目要求来。

前两项可以靠刷题和总结来补,第三项是最容易被忽视、也最容易一晚上丢掉几十分的。我个人的观察是,复试里"完全不会做"的题占少数,"会做但因为细节写挂"的题占多数。

1.2 400 分是怎么被切碎的:按测试点给分的真实含义

CSP-J 第二轮通常是 4 道题,每题 100 分,满分 400 分。关键在于:每题 100 分不是"全对才给分",而是拆成 10 个左右的测试点,每个点单独评测、单独计分。

这个机制直接决定了你的策略。举个例子,一道题的数据范围写着"n ≤ 10^5,但其中 40% 的数据满足 n ≤ 1000"。那么你写一个 O(n²) 的暴力,虽然拿不到满分,但能稳拿那 40 分。而如果你死磕满分算法,结果比赛结束前没调出来,这 40 分也一起没了。

情况常见做法拿到的分
只会暴力枚举直接写 O(n²)30~50
会正确算法但时间超限优化常数、加剪枝60~80
正确算法 + 细节出错挂掉边界点20~70
正确算法 + 文件读写写错全部 0 分0

这张表我想强调的就是最后一行。文件读写错误在复试里是"团灭"级别的失误——程序本地跑得好好的,交上去所有测试点全部运行时错误或答案错误,因为它读的是一份空文件。这种分丢得最冤。

1.3 开赛前的十分钟,比多写一道题更值

我的习惯是:拿到题目后先花 8 到 12 分钟通读四道题,不做任何编码。这十分钟要产出三样东西:

  1. 四道题的难度排序。一般来说 T1、T2 是基础题,T3、T4 是区分题,但要自己判断哪道更熟。有时候 T3 是你擅长的 DP,T4 是你不熟的图论,那就先做 T3。
  2. 每道题的"保底分方案"和"冲满分方案"。保底方案就是暴力,写完就能拿分;冲满分方案是第二步再想的。
  3. 每道题的文件名和输入输出格式。这一步千万别省,把文件名抄在草稿纸上,比如apple.in/apple.out,写代码时直接照着抄,避免手滑。

还有一个细节:草稿纸上把四道题的"时间预算"写下来,比如 T1 25 分钟、T2 35 分钟、T3 55 分钟、T4 60 分钟,留 25 分钟检查。赛场上没有钟表概念的人,最后半小时一定会慌。

2. 四道题的难度曲线与它们各自的考点标签

复试的题目设置是有明显梯度的。理解这个梯度,你就能在赛场上快速判断"这道题值不值得我花时间"。下面我按位置来讲,不过要提前说清楚:位置不等于难度,偶尔会出现 T2 比 T3 难的情况,别把它当铁律。

2.1 第一题:最容易翻车的地方是读题

T1 的地位相当于"入场券",考的基本是模拟、简单枚举、字符串处理或者公式推导,算法门槛很低。但它的翻车率高得惊人,原因不在算法,而在两点:

  • 题面里的规则描述往往有好几层,比如"每满 10 件打折,折后不足 1 元的部分四舍五入",这种地方漏掉一层条件,答案就全错。
  • 样例太弱。T1 一般只给两三组样例,而且都是"正常情况",边界数据藏在测试点里。

我的做法是:写完 T1 之后,自己造三组数据——最小的、刚好卡在规则边界上的、以及会导致答案比较大的。手工算一遍结果,跟程序输出对拍。这三组数据往往能揪出一半的错误。

举个例子,如果题目里有"向上取整"的除法,(a + b - 1) / b这个写法在 a、b 都是正数时是对的,但如果题目允许 a = 0,结果也没问题;可如果涉及负数,整除的取整方向就跟数学上的"向上取整"不一致了。这种细节,只有你自己造数据才能发现。

2.2 第二题:模拟、枚举与排序的主战场

T2 通常是一道"实现量偏大但算法不难"的题,常见形态有:模拟一个游戏流程、按规则排序并输出、多关键字比较、简单的贪心。这里的考点标签非常清晰:

  • 结构体 + 自定义排序:几乎年年都能用上。sort的第三个参数写比较函数,注意比较函数必须是严格弱序——也就是不能用<=,只能用<,否则在某些实现下会直接运行错误。
  • 枚举 + 剪枝:枚举所有可能,但用条件提前跳掉不可能的。
  • 字符串处理:逐字符扫描、大小写转换、分割。

这里有个很值得说的坑:排序的稳定性。如果题目要求"总分相同时按学号从小到大排",那你必须把学号作为第二关键字写进比较函数里,不能指望sort自己保持原顺序,因为std::sort是不稳定排序。想要稳定,用stable_sort,但更稳妥的做法还是把比较规则写完整。

2.3 第三题:二分、贪心、前缀和、入门DP

T3 开始有"算法味"了。这一档的考点基本就四个方向,我按出现频率排一下:

  1. 二分答案。题面里出现"最大值最小""最小值最大""最少需要多少次"这类字眼,八成是二分。
  2. 前缀和 / 差分。出现"多次询问区间和""多次区间加同一个数"就是它。
  3. 贪心。通常要你证明一个排序规则,或者按某种优先级处理。
  4. 线性 DP / 01 背包。状态定义比较直接,转移方程一两行。

T3 的价值在于它是投入产出比最高的一道题。它不像 T4 那样需要复杂的建模,但分值一样是 100 分。如果你能把 T3 稳定拿下,加上 T1、T2,就是 300 分起步,这在入门级里已经是很有竞争力的成绩。

2.4 第四题:搜索、图论与"暴力能拿几分"

T4 是拉开差距的题,常见方向有:DFS/BFS 状态搜索、记忆化搜索、最短路、并查集、拓扑排序、区间 DP、树上的遍历。它的特点是编码量大、调试时间长,而且很多同学会陷入"我一定要想出正解"的执念里,最后时间全搭进去。

这里必须强调一个策略:T4 先写暴力,再想正解。具体流程是:

  • 先看清楚数据范围,用小数据规模能过的暴力写法(比如全排列枚举、裸 DFS)把框架搭起来,保证能拿到小数据的分。
  • 提交或本地测试确认暴力正确后,再去想优化。
  • 如果优化写不出来,直接保留暴力版本,至少不亏。

我在带学生的时候发现,很多人连暴力都不愿意写,觉得"写了也拿不到满分,浪费时间"。但实际上,暴力往往是理解题目、验证正解的最好工具——你后面写的正解,可以拿暴力来对拍。

3. 高频算法模块的落地精讲

这一部分是我最想细讲的内容。上面讲的是"考什么",这里讲"怎么落地"。每个模块我都会给出模板代码的关键部分和我踩过的坑。

3.1 模拟题:把题面拆成状态、步骤和边界

模拟题的核心不是代码技巧,而是把自然语言的规则翻译成明确的变量和流程。我的固定做法是三步:

第一步,列出所有"会变化的东西"。比如一个排队系统,会变化的是每个人的位置、剩余时间、队列顺序。把这些都定义成变量或数组。

第二步,找出"推进的驱动力"。是时间在推进(每秒做一件事),还是事件在驱动(每处理完一个就触发下一个)?前者用循环遍历时间轴,后者用队列或者递归。

第三步,明确"终止条件"。什么时候结束循环,什么时候输出结果。

一个常被忽略的点是同一步内的先后顺序。比如"先结算伤害再判断死亡"和"先判断死亡再结算伤害",结果完全不同。题面里的动词顺序就是执行顺序,不要自己重排。

// 模拟题的常见骨架:按时间推进 int t = 0; while (!finished) { t++; // 1. 先处理所有到达的事件 // 2. 再推进所有正在进行的任务 // 3. 最后判断是否满足终止条件 if (满足终止条件) break; }

3.2 前缀和与差分:把 O(nq) 降到 O(n+q)

前缀和解决的是"静态数组的区间和查询",差分解决的是"静态数组的区间修改"。这两个东西看起来简单,但它们是 T3 最常出现的抓手。

前缀和的核心公式:

// 预处理 pre[0] = 0; for (int i = 1; i <= n; i++) pre[i] = pre[i-1] + a[i]; // 查询区间 [l, r] 的和 int ans = pre[r] - pre[l-1];

差分的核心公式:

// 对区间 [l, r] 整体加 v diff[l] += v; diff[r+1] -= v; // 最后求一次前缀和还原数组 for (int i = 1; i <= n; i++) a[i] = a[i-1] + diff[i];

坑主要在两个地方。第一,下标从 1 开始。前缀和的pre[l-1]在 l = 1 时要用到pre[0],所以数组必须开到 0 号位并且初始化为 0。第二,差分里r+1可能等于 n+1,数组要开大一位,否则越界。这两个错误在本地跑小数据时不会暴露,一交上去就是运行时错误。

还有一个进阶用法:二维前缀和。遇到矩阵上的矩形求和就用它,公式是容斥原理,画个图推一遍就不容易记错。

3.3 二分答案:把"求最大最小值"变成判定问题

二分答案的思维转变是:与其直接求答案,不如写一个函数判断"答案能不能是 x"。这个判定函数通常比原问题好写得多。

// 求最小的满足条件的值 long long lo = 1, hi = 1e9, ans = -1; while (lo <= hi) { long long mid = lo + (hi - lo) / 2; if (check(mid)) { ans = mid; hi = mid - 1; } else lo = mid + 1; }

这里有三个我反复强调的点:

  • 用lo + (hi - lo) / 2而不是(lo + hi) / 2。后者在 lo、hi 都接近 2×10^9 时会整型溢出,直接变成负数死循环。
  • check函数必须是单调的。二分的前提是"如果 x 可行,那么比 x 更宽松的也一定可行"。如果你的判定函数不满足单调性,二分算出来的结果是错的,而且错得很隐蔽。
  • 二分的边界要想清楚。lo 和 hi 的初始值要覆盖所有可能的答案,宁可开大一点。如果答案可能为 0,那 lo 就该从 0 开始。

浮点数二分又是另一回事,一般直接循环固定次数(比如 100 次)就够了,比用while (hi - lo > eps)更稳,因为 eps 选不好容易死循环。

3.4 动态规划:线性DP与01背包的模板化写法

入门级的 DP 考得不深,但"看出来这是 DP"往往是最难的一步。判断依据有这么几条:题目要求方案数、最优值,并且当前决策会影响后续选择,而问题的结构可以按顺序分解成子问题。

做题流程我固定成四步:

  1. 定义状态。dp[i]或dp[i][j]表示什么?这决定了后面所有推导。通常状态的定义会直接照抄题目的问法再缩小规模。
  2. 写转移方程。考虑第 i 个元素"选还是不选""放在哪里"。
  3. 确定初始值。dp[0]是多少,这决定了边界情况对不对。
  4. 确定遍历顺序。保证计算dp[i]时它依赖的状态已经算好。

以 01 背包为例,标准写法:

// dp[j] 表示容量为 j 时能装下的最大价值 for (int i = 1; i <= n; i++) for (int j = W; j >= w[i]; j--) // 倒序遍历,保证每件物品只用一次 dp[j] = max(dp[j], dp[j - w[i]] + v[i]);

这里最经典的坑是遍历顺序。01 背包必须倒序遍历容量,完全背包才正序。原因在于倒序时dp[j - w[i]]还是上一轮的值,保证了"每件物品只用一次"。这个点理解透了,背包这一块基本就稳了。

再提醒一句数据类型:DP 里的值如果涉及累加,很容易超 int。看到 n 到 10^5、值到 10^9,就老老实实上long long。

3.5 搜索:DFS、BFS、剪枝与记忆化

搜索是 T4 的高频考点,也是区分度最大的地方。三种形态要分清:

  • DFS(深搜):适合"找所有方案""判断是否存在",代码用递归写,注意回溯。
  • BFS(广搜):适合"求最少步数",用队列实现,第一次到达目标时就是最短路径。
  • 记忆化搜索:DFS 基础上加一个数组记录已经算过的状态,本质就是 DP 的递归写法。

剪枝是搜索拿分的关键。常见的剪枝手段:

剪枝类型适用场景效果
可行性剪枝当前状态已经不可能达成目标直接砍掉整棵子树
最优性剪枝当前花费已经超过已知最优解极大提速
顺序剪枝优先搜更可能成功的分支更快找到解
记忆化状态会重复出现指数级降到多项式

写 DFS 时最容易犯的错误是忘记回溯。比如访问标记vis[i] = true之后,递归返回时没有置回 false,导致后续分支全部被误判为"已访问"。这种 bug 在小数据上可能看不出来,大数据上直接答案错。

另一个坑是递归深度。DFS 递归层数如果超过几万层,可能会栈溢出。这种情况要么改成迭代写法,要么显式开一个大栈——不过考试环境不一定允许改栈大小,所以更保险的做法是评估一下深度上限,必要时换思路。

3.6 图论与并查集:建图是第一道坎

入门级的图论通常是这几种:最短路(Dijkstra、Floyd)、最小生成树(Kruskal)、拓扑排序、并查集。算法本身模板化程度很高,真正容易出问题的是建图。

建图有三种常见存储方式:

  • 邻接矩阵:g[i][j],适合点数很少(n ≤ 500)的情况。
  • 邻接表(vector 版):vector<int> g[N],适合稀疏图,写起来最方便。
  • 链式前向星:用数组模拟链表,效率高但代码稍复杂,入门级一般用不上。

并查集是这里面性价比最高的,二十行就能写完,出现频率也高:

int fa[N]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); // 路径压缩 } void merge(int a, int b) { fa[find(a)] = find(b); } // 初始化 for (int i = 1; i <= n; i++) fa[i] = i;

这里必须提一句初始化。并查集忘记初始化,或者只初始化了前几个元素,是复试里非常典型的一类错误。另外,如果题目需要统计连通块数量,别忘了先全都初始化成自己,否则计数会错。

3.7 数论与位运算:那些"看着难其实很套路"的题

数论在入门级里主要考这几样:质数判断与筛法、最大公约数、快速幂、同余运算。位运算则常出现在"异或和""状态压缩"这类题里。

筛法的标准写法(埃氏筛)要注意从 i² 开始标记:

vector<bool> isPrime(n + 1, true); isPrime[0] = isPrime[1] = false; for (int i = 2; i * i <= n; i++) if (isPrime[i]) for (int j = i * i; j <= n; j += i) isPrime[j] = false;

从 i² 开始是因为比 i² 小的 i 的倍数已经被更小的质数筛掉了,这样能省不少时间。

位运算里两个必须记住的性质:x ^ x = 0、x ^ 0 = x。这两条是解"找出唯一出现奇数次的数"这类题的关键。异或还具有交换律和结合律,所以一串数异或的结果跟顺序无关——这个性质在"异或和"类题目里经常是破题的入口。

4. 代码工程细节:这些分丢得最冤

前面讲的是"怎么把题做出来",这一节讲的是"怎么不让做出来的题丢分"。说实话,这部分内容没有技术含量,但它是复试里最真实的分数差距来源。

4.1 文件输入输出与评测环境

复试普遍要求文件读写。以题目给定的英文名为准,标准写法是:

#include <cstdio> int main() { freopen("apple.in", "r", stdin); freopen("apple.out", "w", stdout); // 主逻辑 fclose(stdin); fclose(stdout); return 0; }

这里有几个高频事故:

  • 文件名写错字母。题目叫apple,你写成apples,直接 0 分。
  • 路径问题。一般用相对路径就行,不要写绝对路径。
  • 本地调试时把它注释掉,忘记放开。这是我见过最多的事故。本地测试用freopen会读不到数据,很多人就临时注释掉,交卷时忘了改回来。如果用#ifndef或者自己写一个小开关,风险会小很多。
  • cin/cout和scanf/printf混用。一旦加了ios::sync_with_stdio(false),就不要再混用 C 风格输入输出,否则顺序会乱。

至于评测环境,常见的是基于 Linux 的系统,编译器是 g++。我建议平时练习就把标准设成-std=c++14(具体以当年说明为准),语法上避开太新的特性,避免本地能编、评测机编不过的尴尬。

4.2 数据范围决定变量类型

这是复试里最需要"条件反射"的一环。看到数据范围,立刻对应变量类型:

数据范围建议类型说明
≤ 10^4int安全
≤ 10^9int 可以存,但运算要小心两个 10^9 相加就溢出
≤ 10^18long long乘积前记得转换类型
涉及阶乘、组合数long long 或高精度极易溢出

关键点在于:int 的范围约为 ±2.1×10^9,两个接近 10^9 的数相乘就会溢出。解决办法是运算前先转类型,比如(long long)a * b。这个细节不注意,会出现"答案是个莫名其妙的小负数"的现象。

4.3 数组大小、下标起点与初始化

三个小问题,每个都可能让你白丢一道题:

  • 数组开不够。如果 n 最大 10^5,数组至少要开a[100005],留点余量。二维数组更要算清楚:int dp[1005][1005]就是 4MB,开三四个就可能超内存限制。
  • 全局数组会默认清零,局部数组不会。这是 C++ 的规则。把大数组定义在main外面可以省掉初始化的代码,但如果题目需要"每组数据都清零",就得手动memset,尤其是在多组测试数据的题里。
  • 下标从 0 还是从 1。前缀和、差分、树状数组这些结构强烈建议从 1 开始,可以少写很多if (l == 0)的判断。写之前统一一下,别一半从 0 一半从 1。

4.4 输出格式与行末细节

输出格式的坑看起来很小,但真的会扣分:

  • 题目说"每行一个答案",你就不能在末尾多输出一个空行。
  • 题目说"用空格分隔",那行末多一个空格一般能过,但少一个空格一定不过。
  • 浮点数输出要求保留几位小数,要用printf("%.2f", x)这种精确控制,别用cout默认精度。
  • 题目要求输出"Yes"/"No"的大小写,必须完全一致。

我的建议是:写完每道题,回头把题目的"输出格式"那一段再读一遍。这一分钟能救好几十分。

5. 把考点变成分数的训练方法

考点都知道了,接下来是效率问题。备考时间有限,怎么用最少的题量覆盖最多的考点,是有方法的。

5.1 真题怎么用才不是白刷

我见过两种极端:一种是把历年真题当成"收藏品",下载完就放着;另一种是刷完对个答案就算完事。两种都没什么效果。我推荐的做法是三遍法:

  • 第一遍,限时模拟。严格按 210 分钟做完整套,不查资料、不调试过头,模拟真实赛场的紧张感。这次的成绩只是一个基准线。
  • 第二遍,精做。把每道题的正解思路整理成文字,写在自己的本子上。重点是记录"我看到哪句话时应该联想到哪个算法"。
  • 第三遍,盲写。隔两周不看题解,从零把代码重写一遍。如果能顺利写出来,才算真的会了。

特别提醒:整理题库的时候注意来源和版权,优先使用官方渠道发布的题目和解析,自己总结的笔记用于个人复习就好。

5.2 赛时三遍检查法

写完代码不等于结束。我自己的检查流程是固定三遍:

第一遍,对着题面检查逻辑。把题面的每一条规则逐条念出来,问自己"代码里对应哪一行"。这一步最容易发现"漏条件"的问题,而漏条件恰恰是 T1、T2 失分的主因。

第二遍,检查边界。手动构造几组数据:最小规模、最大规模、全相等、全不同、刚好卡在规则分界点上。特别是循环的起止条件,i < n还是i <= n,这类错误只有靠边界数据才能暴露。

第三遍,检查工程细节。文件读写是否打开、数组是否够大、变量类型是否会溢出、输出格式是否符合要求。这一遍不涉及算法,纯粹是排错清单。

5.3 不会做也能拿分的骗分写法

"骗分"不是作弊,是在数据分组评分机制下合法地拿部分分。常用的手段有:

  • 特判小数据。如果 n 很小的情况能用公式或者暴力直接算,就单独写一个分支处理,稳拿这部分分。
  • 输出固定值。有些构造题的测试点里有大量"特殊情况",比如答案就是 0 或 -1,直接输出也可能蒙中若干测试点。这招风险大,只作为最后几分钟的兜底。
  • 写暴力而不是空着。一道题你完全不会,写个 O(n²) 或 O(2^n) 的暴力,能拿的分一定比 0 多。
  • 优先保证能编译通过。写不完的题,把能写部分写完整,剩下一段用// TODO标出来但保证语法正确。交一个能编译的残缺程序,总好过交一个编译错误的文件。

5.4 一份按周推进的备考节奏

如果距离复试还有四到六周,我建议这样安排:

  • 第 1 周,语法与工程细节补缺。把文件读写、结构体排序、字符串处理、long long这些基础工程能力练熟,写五到十道模拟题。
  • 第 2 周,把 T3 的四个抓手过一遍。前缀和、差分、二分答案、线性 DP,每个方向做三到五道题,重点是总结"题面特征 → 算法"的映射。
  • 第 3 周,主攻搜索和图论。DFS、BFS、剪枝、并查集、最短路,这部分要花的时间最多,别怕慢。
  • 第 4 周,全真模拟。每周做两套完整的历年真题,限时 210 分钟,做完立刻复盘。最后三天不再做新题,只把错题重写一遍。

这个节奏的核心是:前期补工程,中期练算法,后期练节奏。很多人反过来,前期猛刷难题,后期才发现自己连文件读写都会写错。

最后分享一个我自己用了很多年的小习惯:建一个"错误清单"文件,每次调试花了超过十分钟的 bug,都记一行——错在哪、为什么错、以后怎么避免。到了复试前一天晚上,只翻这个清单,不翻题解。我个人的体会是,这份清单上的每一条,都是从真实的丢分里换来的,比任何一份"考点大全"都更贴近你自己的短板。等到考场上你条件反射地检查文件读写、检查数组大小、检查long long的时候,就会明白这份清单的价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 1:12:29

故障录波器实战解析:从启动原理到典型波形分析方法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:11:48

YOLOv8教室人数统计实战:从数据标注到部署的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:10:57

SCR ESD器件回滞特性原理与Vh工程设计全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:10:57

2021年中国自然保护区矢量面数据:GIS叠加分析与分区统计实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:10:32

01背包进阶:求方案数与字典序最小方案详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:09:56

Java Web毕设实战:JSP+Servlet+MySQL家电销售系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华