先写能验证的基线,再稳稳升级
这一课只练一件事:遇到一道暂时写不出满分算法的难题时,先写一份能验证的,再逐步升级,而不是一步到位地追求最优解。做法是:先用最直接的写法覆盖小数据,标注它能处理的范围和会漏掉的,再动手做,同时用确认没有引入。必会:能先写小数据可过的基线;能标注它的适用范围和已知会出错的特殊情况;能避免把破坏正确性的“捷径”当成优化。最小示例:区间求和题,q 次查询每次给出 l, r,求 a[l..r] 的和。基线写法是每次查询都从 l 循环到 r 直接累加,复杂度 O(n·q),在 n、q 都不大时能过。样例追踪:先写这份基线并用样例测试通过;标注 l > r 是空区间应输出 0、l == r 是单点区间;再引入前缀和 sum[i] = sum[i-1] + a[i],把每次查询变成 sum[r] - sum[l-1],复杂度升级为 O(n+q);升级后用基线在小数据上对拍,确认输出完全一致。边界是不能跳过基线直接想前缀和公式、也不能为了让代码“看起来更快”而删掉必要的下标或判断。建议掌握:升级前先标好基线的适用范围,升级后立刻用基线做一次对拍,而不是假设新写法一定正确。拓展:伪优化是指看起来精简了代码、实际上悄悄改变了结果的“假优化”,现在只需要能识别一个例子。这里不会在浏览器里运行 C++。
任务 1:先选出该怎么开始
先确定面对一道暂时写不出满分算法的题时该先写什么,再确定写完之后该怎么标注。点不认识的词可看基础解释。
必会:能说出为什么要先写暴力基线;能说出基线写完之后要标注哪些内容。这里不会在浏览器里运行 C++,只练习选择和走过程。
区间求和题,q 次查询每次给 l、r,求 a[l..r] 的和。你还没想出前缀和,应该先做什么?先写什么 · 必会
暴力基线写完并测试通过后,应该怎么处理?标注限制 · 必会
任务 2:按基线、标注、升级三步稳步推进
最小示例:区间求和题,数组 a 长度为 n,q 次查询每次给出 l, r,求 a[l..r] 的和。按顺序点三步:先写,再标注,最后做。这里不会在浏览器里运行 C++。
必会:能解释每一步为什么这样做。边界:不要跳过“标注特殊情况”直接升级;升级后必须用基线做一次对拍,确认新写法没有改变结果。
- // 题目:数组 a 长度 n,q 次查询,每次给 l、r,求 a[l..r] 的和
- // 基线:每次查询从 l 循环到 r 直接累加,复杂度 O(n·q)
- // 标注:l>r 是空区间(输出 0);l==r 是单点区间;n、q 小时基线可过
- // 升级:引入 sum[i]=sum[i-1]+a[i],查询变成 sum[r]-sum[l-1] → O(n+q)
三步走完了:基线锁住了小数据的分数,特殊情况标注清楚,升级后的版本也保留了基线用来对拍。现在把的查询算式亲手敲一遍,特别注意那一格。下面是只读脚手架,已经建好,只留一空给你输入;这里不会在浏览器里运行 C++。
- // 题目:数组 a 长度 n,q 次查询每次给 l、r,求 a[l..r] 的和
- int a[6] = {0, 3, 1, 4, 1, 5}; // 下标从 1 开始用:a[1] 到 a[5]
- int sum[6]; // sum[i] 表示 a[1] 到 a[i] 的和
- int main() {
- for (int i = 1; i <= 5; i += 1) sum[i] = sum[i - 1] + a[i];
- int l = 2, r = 4; // 查询 a[2..4],手算应是 1 + 4 + 1 = 6
- cout << << "\n"; // 一行查出 a[l..r] 的和
- return 0;
- }
cout << sum[r] - sum[l - 1] << "\n"; // 左端点减的是 l 前面那一格,别写成 sum[l]
任务 3:识别伪优化,并确定怎么验证升级
建议掌握:把 O(n·q) 的基线升级成 O(n+q) 的前缀和之后,要立刻用基线做(对拍),确认输出完全一致。拓展:是指看起来更简洁、实际上悄悄改变了结果的写法,现在只需要能认出一个例子。
必会 / 建议掌握 / 拓展:必会是先写基线、标注特殊情况、避免伪优化。建议掌握是升级后立刻对拍验证。伪优化的具体识别是拓展,现在不用当硬门槛。
- // 正确升级:sum[i] = sum[i-1] + a[i];查询 sum[r] - sum[l-1]
- // 伪优化:有同学为了“少写一次减法”,把查询改成 sum[r] - sum[l]
- // 后果:多减掉了 a[l],区间 [l, r] 少了左端点的值,结果比正确答案少 a[l],属于伪优化
- // 验证:同一组小数据,基线和前缀和版本各跑一次,比较输出是否一致(对拍)
先判断这是不是伪优化:
再选出升级后该怎么验证:
任务 4:随机小测,看看你是否真的懂了
每次从本课题库抽出三道不同的选择题。题目与解析已通过校验,答完后看解析,不要只看分数;拿不准就回到对应任务再看一遍。