可达信奥 · 考场代码诊断
CSP-J 2026 第二轮 · 准考证号 431392 · 2026-11-13

第二题 nailoong,0 分。
读入没问题,
卡在建模这一步。

这一份只说第二题喷水小奶龙。旭扬把输入读完了,文件名也没写错,代码是跑完的;0 分是因为题里龙喷湿的是右侧一整段,旭扬看成了两个相邻格子,安全位置怎么判也跟着偏了,下标还对错了一位。下面对着代码逐行说。

学生朱旭扬
准考证号431392
学校合肥市琥珀名城小学教育集团明皇路小学
年级 / 县区五年级 · 瑶海区
本次聚焦T2 · nailoong · 0
成绩单 · 第二轮认证(第二题记录)
$ 打开 CSP-J 2026 第二轮 成绩与申诉
nailoong0区间看成两个点,判据也换了
总成绩 210(其余三题不在本报告展开)
总成绩
210/ 400
CSP-J 2026 第二轮认证
本次分析题目
0/ 100
读入、文件名都对,问题在思路
第二题为什么是 0

龙喷湿的是 \([p_i,\,n]\) 一整段,代码只标了 \(p_i\) 和 \(p_i-1\) 两个格子

这题 0 分,但不是流程上出的问题。文件名 nailoong.in / nailoong.out 和题面一致,\(n\) 和位置都读进来了。看第 20 行:每来一只龙,代码只把 \(\{p_i,\ p_i-1\}\) 记成已占,再数还剩几个没标记的格子。题面里这只龙从 \(p_i\) 一直喷到 \(n\),是右侧一整段;能躲的位置,是站在所有龙位置的左边。代码数的是"没被点到的格子",判据变成剩余格子数 \(>1\),和题目问的"有没有至少一个安全位置"已经不是一回事。

01

第二题的读入、处理、输出

按三段拆开,问题出在哪一段

nailoong 一共 36 行,输入和输出都没出错,问题在中间处理这一段:安全位置还没在纸上想清楚,代码已经开始标格子了。

T2 nailoong
36 行
读入 · 对\(n\) 个位置全部读完
→
处理 · 崩区间喷水看成两个点,判据换成剩余格子数
→
输出 · 对YES / NO 逐行写出
思路偏了,后面标记再仔细也对不上。
01
喷水范围看成两个相邻格子nailoong.cpp 第 20 行\(\texttt{nx[2] = \{a.at(t), a.at(t)-1\}}\)。题面里龙喷湿的是后缀区间 \([p_i,\ n]\),代码只留了 \(p_i\) 和 \(p_i-1\) 两个点。
02
判据换成数剩余格子,条件还多要一个nailoong.cpp 第 16、24、27 行题目只问有没有至少一个安全位置,正解判 \(\min_{j\le i} p_j>1\);代码改成数未标记格子 \(\texttt{num}\),还要求 \(\texttt{num}>1\)。数的东西换了,门槛也抬高了一个。
03
位置编号和数组下标没对上nailoong.cpp 第 20、22 行题面位置编号是 \(1\ldots n\),数组下标是 \(0\ldots n-1\);代码直接拿 \(p_i\) 当下标,位置 \(n\) 越界被跳过,位置 \(1\) 又落到了下标 \(1\)。
02

对着代码看第二题

写到哪里、哪里对、错在哪一行

下面贴的是旭扬自己的 nailoong.cpp,出问题的行我标了底色,可以对着原文件核;卡片后面是正解思路,以及我上课准备怎么带旭扬改。

T2

喷水小奶龙

nailoong 建模偏差,整题归零 0/ 100
机房位置 \(1\ldots n\),每秒在 \(p_i\) 刷新一只小奶龙,所有 \(p_i\) 互不相同;龙在自身位置及右侧喷水。每加入一只,判断此时是否还存在至少一个位置躲开所有已出现的龙,逐行输出 YES / NO。
题面:龙从所在位置向右,喷湿一整段后缀 安全位置 {1,…,mi−1} 1 2 3 龙 · 4 5 6 7 8 喷湿后缀 [pi, n]:位置 4 到 8 都在水里 代码:只把 pi 和 pi−1 两个格子标成已占 1 2 3 4 5 6 7 8 误标的两个点 右侧 5–8 漏标,其实都在喷水范围内 安全位置 龙所在位置 喷湿 / 误标 未覆盖
示意取 \(n=8\)、龙出现在位置 4。正解边读边维护当前最小位置 \(m_i\),看 \(m_i>1\);代码把后缀区间缩成两个点,右侧整段没有覆盖。
正解其实只要记一个最小值。安全位置 \(x\) 得在每只龙的左边,也就是对所有 \(j\le i\) 都有 \(x\lt p_j\)。记 \(m_i=\min_{j\le i}p_j\),那能站的位置就是 \(1,\ldots,m_i-1\);有没有安全位置,看 \(m_i>1\) 就行。边读边把最小值带上,一遍过,\(O(n)\)。
代码这几处和题面对不上。
  • 第 20 行把喷水范围记成 \(\{p_i,\ p_i-1\}\) 两个格子;题面里喷湿的是后缀区间 \([p_i,\ n]\)。
  • 第 16、24 行用布尔数组逐个标记,再数未标记格子 \(\texttt{num}\)。安全位置不是"没被点到的格子",是"所有龙位置左边的格子"。
  • 第 27 行 \(\texttt{num}\le1\) 就判 NO;题目只要求至少一个,正解看的是 \(m_i>1\)。数的东西换了,门槛又多要了一个。
  • 第 20、22 行下标平移:位置 \(n\) 越界被跳过,位置 \(1\) 落到下标 \(1\),安全区的边界对不上。
文件名和读入都没问题,0 分是思路这一步偏的,不是流程丢分。
朱旭扬的原文(nailoong.cpp 第 15–33 行)
int num = n; vector<bool> d(n, false); bool ok = true; for(size_t t = 0;t < a.size(); t++){ if(ok){ int nx[2] = {a.at(t), a.at(t) - 1}; // 第 20 行:只标两个格子 for(int i = 0;i < 2;i++){ if(nx[i] < 0 || nx[i] >= n)continue; if(d[nx[i]]) continue; num--; d[nx[i]] = true; } if(num <= 1) ok = false; // 第 27 行:要求剩余 >1 } if(ok) fout << "YES" << '\n'; else fout << "NO" << '\n'; }
正解:边读边维护最小值
int mn = n + 1; for (int i = 1; i <= n; i++) { int p; cin >> p; mn = min(mn, p); // 当前所有龙位置的最小值 cout << (mn > 1 ? "YES" : "NO") << '\n'; }
下次先在纸上画安全区,再决定用不用数组。每只龙留下的安全区是左边一段前缀,所有前缀的交集,就是最靠左那只龙左边的位置。这次是还没画集合,先去标格子了。
知识点:后缀区间与前缀交集知识点:维护前缀最小值易错:把区间看成两个点易错:1-based 下标平移
03

现阶段薄弱点

结合第二题的代码表现看缺口在哪

这题输入、文件名、逐行输出旭扬都没出错,流程上不丢分。差的是拿到题先理结构这一步,下面四条按要紧程度排。

01

拿到题先写代码,没先在纸上理结构

读完题先标格子、数剩余,没先想"安全位置是哪些、题目要的判据是什么"。这题把后缀区间看成两个点,主要就是结构还没理清,代码就先下去了。

02

一侧 / 一段的题,还在逐个标格子

这类"站在某一侧、落在某一段"的题,正解是维护前缀最小(最大)值;旭扬写成了布尔数组逐个标记。维护区间极值、取集合交集的写法,还没练熟。

03

题目条件翻不成一个最值判断

"有没有至少一个安全位置",对应的是 min > 1;代码换成了"未标记格子数 > 1",数的东西和门槛都偏了。把题面一句话翻译成 min / max 判断,这一步还不熟。

04

下标和边界不牢

\(1\)-based 和 \(0\)-based 怎么平移、哪里会越界、阈值 \(>0\) 和 \(>1\) 差在哪,条件写了但位置对不上。位置 \(n\) 被跳过、位置 \(1\) 落错下标,属于这一类,不是思路完全不会。

04

后续怎么训练强化

本周理结构和边界,两周补前缀最值,赛前集中练同类题

底子不用重搭。这题输入输出都稳,丢的是建模和边界,算不上全新知识,带着练两三周能看到变化。下面分三步,每步写了怎么算过关。

本周

把"先理结构、再写下标"做成习惯

目标:动笔前先把结构和边界想清楚,再开编辑器
  • 每题先写三句:安全位置是哪些、判据是什么、哪部分可以不动,想完再写代码
  • \(1\)-based / \(0\)-based 下标先对照一遍,越界位置用 \(n=1\)、端点各跑一遍
  • 阈值 \(>0\) 和 \(>1\) 分开,拿边界小样例验过,不凭感觉写条件
验收:拿这道题,能说出安全位置是所有龙位置左边的格子
两周内

补前缀最值写法,这题回炉重写

目标:见到一侧 / 一段的题,先想到维护极值
  • 前缀最小 / 最大:边读边带上,不用布尔数组逐个标记
  • nailoong 照正解思路手写一遍,对着原稿看差在哪一步
  • 再练 3–5 道同类区间、前缀交集题,先写集合再写代码
验收:不看题解能写出"边读边维护最小值",并说清判据 \(m_i>1\) 怎么来的
赛前

同类一侧 / 一段题集中过一遍,错题回炉

目标:从逐个标格子,走到先理结构再写
  • 把这题三处错因记在一页上:区间看成点、判据换对象、下标平移,各一条
  • 赛前再做一组区间最值、集合交集题,每题先口述安全位置,再落代码
  • 回炉时逐行对照原稿,确认同类边界条件不再漏
验收:能用自己的话讲清,为什么先画安全区,再决定用不用数组标记
做题前 / 交卷前自检清单0 / 6
读入和文件名都对,问题在思路:龙喷湿的是右侧整段 \([p_i,n]\),代码只标了 \(p_i\) 和 \(p_i-1\) 两个格子;安全位置又被换成"未标记格子",判据和题目问的"有没有至少一个安全位置"对不上。
理解偏了。正解只要带上当前最小位置 \(m_i\),判 \(m_i>1\);代码用布尔数组逐个标记,把区间题做成了数格子。这一步补回来,同类题的思路就能接上。
算边界习惯不牢。题面位置 \(1\ldots n\)、数组下标 \(0\ldots n-1\),动笔前没先对照;位置 \(n\) 越界跳过、位置 \(1\) 落错下标,拿边界小样例就能拦住,不需要补新知识。
先补前缀最值和区间集合这一块,同时把"先理结构、再写下标"练成习惯。节奏见上面三步,每步都写了怎么算过关。
最后说一句。旭扬不是代码写不出来:这题读入、逐行输出和文件名都稳,流程上没丢分。差的是理清结构这一步——区间还在逐个标格子,判据和下标边界也没扣严。把前缀最值写法和这套检查习惯补上,下次碰到同类题能接住。