UOJ Logo liu_cheng_ao的博客

博客

【欢迎投稿】「思考题研讨」这一训练形式的介绍以及例题

2025-11-07 22:05:37 By liu_cheng_ao

个人著作权声明:严禁任何未经本人(刘承奥,常用笔名/网名:蔡德仁 CommonAnts LCA liu_cheng_ao)书面授权者在梦熊联盟,或者任何虚假宣传或不实营销炒作或不正当竞争行为严重的 OI 机构的课程内或交流平台(包括但不限于品牌集训线下讨论,交流群,OJ,公众号,视频号等)上引用、传播、讨论此内容,以及本人于2024年5月及之后发布的所有内容,包括声明为公开的内容在内。

本文在 LibreOJ 最快更新!

所谓 「思考题研讨」,是一种在大学中亦有记载的算法学习方式。每个思考题是一系列相关的具体算法数学问题,围绕一个技巧/数学概念/动机等小套路展开,用于补足编程题不能表达的内容。毕竟编程题只能表达编程内容。每个思考题应当包括至少一道 OI 题或一个经典数学概念。

思考题的通常用法是几个同学小组讨论做法,之后再讲解或者看题解。当然,如果没有同学的话单人学习也是可以的。

同学们偶尔想到的那些不太实用/偏/怪/卡常/重复造轮子的灵感非常适合造思考题研讨

笔者这一年来(截至 2025 年 11 月)协同助教和网友已经造了思考题 80 余道。以下展示一些笔者认为较为不错的思考题作为例子,欢迎大家讨论!

笔者造的和征集的思考题中优质的都会在之后的教材编写、公开资源推荐等中陆续公开。也欢迎各位投稿的同学自行公开传播自己造的思考题。

目前只造了 NOIP+ 和 NOI 难度的思考题,不过该形式在入门和普及学习简单编程基础和数学知识也是有用的,欢迎各位集思广益。

有奖征集思考题:【欢迎投稿】有奖征集 OI 小知识点,技巧和思考题,包括“广为人知”但大纲未收录的内容!

思考题题例(题解之后公布)

  • 以下例题中题号 AP 是面向 NOIP+ 难度;题号 A 是面向 NOI 难度。注意因为思考题默认是要多人研讨的,会比同阶段 OJ 题更难。
  • [bonus] 是开放性或者困难的问题,给水平特别高的同学进阶讨论。

A101 大鱼吃小鱼

有一排 $n$ 条鱼,每条鱼有一个体型值(正整数)$a_i$,一条鱼可以吃掉相邻的鱼,如果被吃的鱼体型小于等于自己。吃完后自己的体型会加上被吃的鱼的体型。鱼之间位置的先后顺序不变。

问题1. [ARC189D]每条鱼最多可以吃到多大的体型?

问题2. [P9530]单点修改 $a_i$,区间查询 $[l,r]$ 内有多少条鱼可以吃完区间内其它所有鱼。(只有这个问题有修改和查询)

问题3. 如果我们有一种道具,鱼每用一次道具可以吃掉任意一条相邻的鱼,无视体型,请你对于每条鱼求出,它吃完所有其它鱼最少需要多少个道具。

问题4. 如果我们把吃鱼的规则改为只能吃右边(编号更大)和自己相邻的鱼(道具不受影响),问题2和3的结果会有什么变化?(你不能先操控别的鱼吃鱼,再用道具吃它)

问题5. 如果我们允许小鱼吃大鱼,也就是定义常数 $k(k\ge 0)$,将题目条件改为“一条鱼可以吃掉相邻的鱼,如果被吃的鱼体型小于等于自己的体型加 $k$”,问题3的结果会有什么变化?

问题6 [JS2024/U477940]:如果我们去掉问题5中 $(k\ge 0)$ 的限制,问题5的结果会有什么变化?

问题7. 如果我们把问题5和6中的条件从差值改成比例,也就是定义常数 $c(c\gt 0)$,将题目条件改为“一条鱼可以吃掉相邻的鱼,如果被吃的鱼体型小于等于自己的体型乘 $c$”,问题5和6的结果会有什么变化?

问题8.[bonus] 尝试找到一个有意思的问题并改编一个 OI 题目。例如:如果我们把鱼放到树上,定义每条鱼占据一个树上连通块,两条鱼相邻当且仅当占据的连通块相邻,初始每条鱼占据一个点,被吃的鱼的连通块会被吃它的鱼占据,会发生什么?

A102 循环博弈

有 $n$ 个人在玩游戏,有一堆初始总数为 $m$ 的石子,从第 $1$ 个人开始轮流取(第 $n$ 个人后再次轮到第 $1$ 个),每次每个人需要拿走至少 $1$ 个至多 $k$ 个石子。如果轮到一个人时石子没有了,游戏结束。定义游戏的结果为游戏结束时轮到的人的编号。

现在有一个 $n$ 行 $n$ 列的矩阵 $A$,其中 $A_{i,j}$ 表示如果游戏结果为 $i$,第 $j$ 个人会获得 $A_{i,j}$ 的收益。保证 $A$ 每一列的元素互不相等,不妨设 $A$ 的每一列都是 $1$ 到 $n$ 的排列。

每个人都想最大化自己在游戏结束后的收益,他们也知道所有人都这么想。

问题1. 讨论里所有人都最大化自己的收益在实际游戏中会怎么决策,说明每个人有确定的决策。

(并不是所有博弈都有符合直觉的确定的最优策略。例如,在一些多人游戏中经常发生某个人已经必败了但他可以选择其它人谁赢。这时你不能仅凭每个人都最大化自己收益来确定他的选择。想想这个题为什么没有类似情况。)

问题2. 给出一个关于 $n,m,k$ 的多项式时间的算法求出最优策略。

定义 $f(x,y)$ 表示轮到第 $x$ 个人且石子还剩 $y$ 个时,所有人都采取最优策略的情况下游戏的结果。

问题3. 证明 $f$ 关于石子个数存在周期。换言之,存在正整数 $T$ 使得不满足 $f(x,y)=f(x,y+T)$ 的正整数 $(x,y)$ 只有有限多对。

问题4. 考察 $n\le 3$ 时 $f$ 的情况。例如考虑:不满足周期的最大数对的上界是多少?最小正周期的上界是多少?如何构造?$f(1,\cdot)$ 和 $f(2,\cdot)$ 两列值有什么关系?(将 $k$ 视为参数)

在此基础上提出一个尽可能高效的算法计算 $n\le 3$ 时的这个问题。

问题5. 现在取消对 $n$ 的限制,考察 $f$ 的最小正周期和非周期部分的上界,并给出使之渐进尽量大的构造。(将 $n,k$ 视为参数)

这个问题比较困难,所以我们给出一些提示。另外,不要忘记打表观察也是一种方法。

混循环数列不容易处理,我们考虑纯循环,也就是说,令 $g(x,y)$ 是一个函数对任意整数 $y$ 和 $1\le x\le n$ 都满足 $g(x,y)=g(x,y+T)$ 且存在 $M$ 使得 $\forall y \gt M, g(x,y)=f(x,y)$。研究 $g$ 也可以得到循环节的性质。

例如:记 $g_x$ 表示数列,$g_x[y]=g(x,y)$(下标 $y$ 是包括负数在内的全体整数)。考虑:

问题5.1. $g_x$ 和 $g_{(x \bmod n)+1}$ 两个数列之间有什么递推关系?

问题5.2. 根据 5.1 的递推关系,如何直观刻画 $g_x$ 更方便?

问题5.3. 我们不妨设 5.1 的递推关系为 $g_x=P(g_{(x \bmod n)+1})$,那么我们知道 $P^n(g_x)=g_x$,也就是 $P^n=I$ 作用是保持不变,尝试通过 $P^n$ 的这一性质来研究周期的性质。

问题5.4. 我们不妨设原本的序列也有规则相同(但定义域不同)的递推 $f_x=P(f_{(x \bmod n)+1})$,尝试通过 $P$ 反复迭代过程中 $f$ 的变化过程研究非周期部分的上界。

问题6. 找到原问题的一个真正的多项式时间算法,也就是关于输入长度的多项式,即使 $m,k$ 是高精度的。给出你算法的时间复杂度上界。

问题7.[bonus] 研究这个问题的一些特殊情况或拓展情况,并尝试出题。例如:如果我们规定矩阵 $A$ 的值是 $A_{i,j}=(i+j-2)\bmod n+1$ 会发生什么?如果 $k=\infty$ 会发生什么?如果 $A$ 的一列内有多个相同数字,会对最优策略的概念产生什么影响?

A103 全局平衡

你有 $n$ 个数 $a_1,a_2,\dots ,a_n$。现在你要构造出一棵 $n$ 个叶子的有根二叉树,把这些数分别填入每个叶子。定义一个叶子走到根的代价等于它填的数加上到根距离。(树没有边权)

你希望让所有叶子走到根的最大代价尽可能小,并求出这个最小值。

问题1. 假如这些数是 $n/x$ 个 $x$ 和 $n-n/x$ 个 $1$($x$ 是一个参数),你能求出问题答案大致的大小吗?

问题2. 输入这 $n$ 个数,请你设计算法并写一个程序求解这个问题。

问题3.

我们知道在二叉搜索树(有根有序二叉树)上,每个子树对应中序遍历的一个区间。

现在,你有 $n$ 个点和 $m$ 个区间约束 $[l_i,r_i],1\le l_i\le r_i\le n$。你要构造一个二叉搜索树,使得在树的中序遍历上,每个约束区间 $[l_i,r_i]$ 都恰好对应某一棵子树里的所有点。

问题3.1:输入 $m$ 个区间,输出是否存在这样的二叉搜索树。

问题3.2:输入 $m$ 个区间,构造一棵深度尽量小的满足条件的二叉搜索树。

问题4.

我们知道在一些数据结构问题中,经常出现这么一种“树套树”的情况:我们有很多个二叉搜索树,当我们查找到上层的二叉搜索树的叶子时,我们需要转到这个叶子关联的下层二叉搜索树,继续递归查找。或者反过来,从一个叶子不断向上跳,当跳到根时,根可能关联了一个上层二叉搜索树的叶子,我们需要转到那个叶子继续向上跳。

例如,在树链剖分中,如果我们给每个链开一个二叉查找树维护链上的所有点,查询一个点在原树上到根路径的过程就可以描述为不断在当前链对应的二叉搜索树上向上跳,到搜索树根之后再跳到当前链的链顶在原树上的父节点。这个点属于另一条链,然后我们继续在它的链搜索树上往上跳。循环往复直到跳到原树根节点所在的链的搜索树根。

现在给定一个有根树的树链剖分方式,所有 $n$ 个树上的点被分成若干个祖先到子孙方向的链。请你找出一种二叉查找树形状的设置方法,使得在最坏情况下查询一个点在原树上到根路径的过程向上跳的步数尽可能少。你可以以此分析一下,假如树链剖分方式分别采用重链剖分和长链剖分,跳的步数复杂度是多少?

(在重链剖分时,这个算法在OI中被称为“全局平衡二叉树”)

问题5.

现在我们看这样一个问题:

你和小明玩猜数游戏。有一张纸上面写了一些实数(设为数集 $S$)。一开始,小明选一个在集合 $S$ 里的数记在心里。然后每次你可以做两种询问: - 询问一个整数 $x$,小明回答他的数和 $x$ 的大小关系。 - 询问一个实数 $x$,小明回答他的数是否等于 $x$。

请你设计一个足够优的策略使得最坏情况下询问次数尽可能少(渐进足够少即可),找出你表示这个询问次数需要从 $S$ 中提取的关键信息/参数。并且给出最坏情况下询问次数的估计。

问题6.

在问题5的基础上,你和小明从猜数升级到了猜点。

有一个平面上的点集 $S$(不妨设为用两维实数坐标表示)。

一开始,小明选一个在集合 $S$ 里的点记在心里。然后每次你可以做两种询问: - 询问一个网格直线 $x$,小明回答他的数在直线 $x$ 的哪一侧,或者恰好在直线上。(指水平或垂直且坐标为整数的直线) - 询问一个任意直线 $x$,小明回答他的点是否在这条直线上。

请你设计一个足够优的策略使得最坏情况下询问次数尽可能少(渐进足够少即可),找出你表示这个询问次数需要从 $S$ 中提取的关键信息/参数。并且给出最坏情况下询问次数的估计。当然,这个问题可以对两维分别做一次问题5,你能做到更优吗?

A032 中位数和第 k 小

(本问题中的中位数,在数字个数为偶数 $n$ 时指从小到大排名第 $\lceil n/2\rceil$ 的数,类似概念均如此取整,以保证中位数一定在输入之中。否则对于字符串之类可以排序但不能平均的对象无法定义中位数。)

问题1. 小明得到了一个程序,它可以输入一个长为 $n$ 的数组,然后在 $O(n)$ 时间内计算出这个数组内中位数的下标并返回。小明可以任意次调用这个程序,现在他想设计一个算法,输入 $n$ 个数和整数 $k$,在 $O(n)$ 时间内输出其中从小到大排第 $k$ 小的数,能做到吗?

如果把计算中位数改成随机取一个数,会对你的程序效率产生什么影响?是否存在一个特定输入总能“卡掉”该算法?

问题2. 小明构思了两个程序,程序1输入一个长为 $n$ 的数组,然后在 $O(n)$ 时间内计算出这个数组内中位数的下标。程序2输入一个长为 $n$ 的数组,在 $O(n)$ 时间内输出其中从小到大排第 $\lceil rn\rceil$ 小的数的下标,其中常数 $r$ 是一个区间 $(0,1)$ 内的固定的比例参数。

如果小明已经有了程序1,如何利用程序1设计出程序2?

如果小明已经有了程序2,如何利用程序2设计出程序1?

你的办法的时间的常数系数和 $r$ 有什么关系?

问题3. 小明突发奇想,他把 $n$($n$ 很大)个数分成了 $n/999$ 组,每组 $999$ 个数。然后他计算出了每组内部的中位数(这可以在 $O(n)$ 时间内暴力完成,毕竟 $999$ 只是个常数),又计算出了这 $n/999$ 个中位数 $m_1,m_2,\dots ,m_{n/999}$ 的中位数 $M$。请问这个“中位数的中位数”$M$ 在最开始的数组中最大和最小的排名范围大致是多少?(不必考虑多个数相等的情况,可以认为是取了更优的一个)

如果“计算 $n/999$ 个数的中位数”这一步递归计算,时间复杂度是多少?(提示:为了可以递归,不妨把整个问题理解为求第 $k$ 小,而不只是中位数)

问题4. [median of medians] 根据问题3设计一个在最坏情况下渐进复杂度低的中位数算法,并思考有多个输入数相等时的运行情况。当然,这可以用于问题1和问题2。

问题5. 现在你有 $n$ 个,每个长为 $m$ 的递增序列,你想要选出所有序列合在一起的第 $m$ 小元素。请你给出一个时间复杂度尽可能小的做法。(不考虑读入时间。)

问题6. 请你解决 https://uoj.ac/contest/91/problem/891

问题7.[bonus] 你有一个 $n\times n$ 的递增矩阵($a[i][j]\lt a[i+1][j]$ 且 $a[i][j]\lt a[i][j+1]$),你想要选出矩阵的第 $n$ 小元素。请你给出一个时间复杂度尽可能小的做法。(不考虑读入时间。)

拓展阅读.[bonus] https://www.cnblogs.com/zkyJuruo/p/18428124

A029 无删除双指针

你在一个 $n\times n$ 的网格上,初始在左上角 $(1,1)$,设 $(x,y)$ 表示从上往下第 $x$ 行从左往右第 $y$ 列的格子。这个网格中每个格子都是黑白两种颜色之一,并且白格的左、上方都是白格,黑格的右、下方都是黑格。你可以且只能看到你当前所在的格子的颜色(当然你可以思考和记录之前看到的东西)。你想搞清楚整个网格每个格子的颜色。

问题1.1. 如果你可以向四个方向的相邻格走,请你给出一个步数上界尽可能少的算法。

问题1.2. 如果你只能向左右下三个方向的相邻格走,请你给出一个步数上界尽可能少的算法。

问题1.3. 现在网格的地面倾斜了,左上方高右下方低。因此,你只能向右或者向下的相邻格走。当然只有这样是不可能探索整个网格的。所以你拿来了一条绳子,它被固定在你经过的每个格子里,这样,你就可以顺着绳子攀爬,收回最后一格绳子同时返回绳子的上一格。(也就是说任何时候绳子都是一条从 $(1,1)$ 沿着你之前走的路径向右向下到达你当前位置的折线)

问:如果你想要到达对角线($x+y=n$)上的每个格子 $(x,y)$ 一次,总共至少要走多少步?

问题1.4. 在上一问的基础上,现在保证网格只有对角线附近未知,$(x,y)$ 所有满足 $x+y\le n-10$ 的都是白格,所有满足 $x+y\ge n+10$ 的都是黑格。请你给出一个步数上界尽可能少的算法。把 $10$ 改为 $k$(仍然保证 $k$ 远小于 $n$),估计步数。

问题1.5. 在上一问的基础上,取消对角线的保证,请你给出一个步数上界尽可能少的算法。

问题2. [baka's trick]你有一排 $n$ 个物品和常数 $W,V$,第 $i$ 个物品的重量为 $w_i$,权值为 $v_i$。称一个下标区间是合法的当且仅当区间内可以选出一个总重量 $\le W$ 且总权值 $\ge V$ 的子集。容易证明如果一个区间合法则包含它的区间都合法,请你求所有极小的合法区间。$1\le n\le 10^4,1\le w_i,W\le 10^4,1\le v_i,V\le 10^9$

问题3. 有 $n$ 个点 $m$ 条边的无向图,点编号 $1\dots n$,边编号 $1\dots m$。请你求出所有极大无环区间,无环区间的定义是只考虑编号在该区间内的边不会形成环。(不要使用 LCT 乃至动态图连通性等复杂数据结构直接维护。)

问题4. 请你解决 https://uoj.ac/problem/693

A027 数对/图的zig-zag构造

问题1. 构造一个 $n$ 阶排列,使得每一对相邻数的差恰好取遍 $1,2,\dots ,n-1$。

有一个 $n$ 个点的有向完全图 $G$,它的边有 $n(n-1)$ 条。在很多构造问题中,我们需要做这样一件事:把这 $n(n-1)$ 条边分成 $n$ 个大小为 $n-1$ 的集合,且每个集合的结构都相同,且足够简单。

一个自然的想法是,先找一个边集 $E$,使得 $n$ 个集合恰好是这个边集的旋转。具体定义如下:

把图中所有点标号为 $0,1,\dots ,n-1$。我们对于边集 $E$ 和整数 $x$ 定义加法:$E+x=\{(u+x\pmod n,v+x \pmod n):\forall(u,v)\in E\}$。也就相当于把图中的 $n$ 个点排成一圈并旋转这个边集。

问题2. 如果一个边集 $E$ 满足 $E+0,E+1,\dots ,E+n-1$ 恰好不重不漏地划分了图里的所有边,$E$ 的性质是什么?(充要条件?)

问题3. 最简单,性质最好的大小为 $n-1$ 的边集应该是哈密顿路径。构造一个满足上述条件的边集 $E$ 使得 $E$ 中的边组成一条有向哈密顿路径。

无向图也有类似的构造。有一个 $n$ 个点的无向完全图 $G$,它的边有 $\frac{n(n-1)}{2}$ 条。在很多构造问题中,我们需要做这样一件事:把这 $n(n-1)$ 条边根据 $n$ 的奇偶性分成 $n$ 个大小为 $\frac{n-1}{2}$ 的集合或者 $n-1$ 个大小为 $\frac{n}{2}$ 的集合,且每个集合的结构都相同,且足够简单。

问题4.1. 最简单,性质最好的大小为 $\frac{n-1}{2}$ 或者 $\frac{n}{2}$ 的无向边集应该是最大匹配。当 $n$ 为奇数时,构造一个边集 $E$ 满足 $E+0,E+1,\dots ,E+n-1$ 恰好不重不漏地划分了图里的所有边,使得 $E$ 是最大匹配。

问题4.2 当 $n$ 为偶数时存在一个边集 $E$ 满足 $E+0,E+1,\dots ,E+n-1$ 恰好不重不漏地划分了图里的所有边,使得 $E$ 是最大匹配吗?如果不能,尝试微调“旋转”的定义使得我们仍能将所有边划分成一组性质良好的最大匹配。(可以结合下面的实际应用思考)

现在我们来看实际应用。注意,“二元组互不相等”形式的约束通常可以图论建模。

问题5. 【QOJ5528】给定一个无向完全图,请你将它的所有边排成一个序列使得这个序列中每相邻 $n-1$ 条边都形成一棵生成树。(实际上,可以排成环形序列。)

问题6. 【P9837】https://www.luogu.com.cn/problem/P9837

问题7. [CF2081F]构造一个 $2n\times 2n$ 的拉丁方(每一行、每一列都是 $2n$ 的排列)满足每一对关于整个矩阵水平或垂直平分线轴对称的位置和都为 $2n+1$ - $a[i][j] = a[2n-i+1][2n-j+1] = 2n+1 - a[2n-i+1][j] = 2n+1 - a[i][2n-j+1]$ - 横着看相邻两个位置组成的有序对(共有 $2n \times (2n-1)$ 个对)全都互不相同 - 竖着看的有序对也互不相同

问题8.[bonus] 这个模式[pattern]可以称为zig-zag。你是否能想到类似的问题和拓展?

更多例题. 【P5419】

A036 我放弃了均摊数据结构

问题1. 小明听说 std::vector 能够维护一个数组,支持在末尾添加、删除元素和随意访问任意下标的元素。为了随意(也称随机)访问,std::vector 将元素存储在一段连续的内存中。

但是,计算机每次只允许申请固定长度的连续内存。我们认为申请一段固定长度的连续内存,无论长度多少都是 $O(1)$ 的。(仅申请,后续修改另外算时间。)

因此 std::vector 的实现方式是,有一个容量值 $C$,添加新元素时一旦超出容量,就将 $C$ 变为原来的 $2$ 倍,申请一段新的长为 $C$ 的内存,并把原来的元素复制过去,释放原来的内存。这个步骤称为重构。

小明想到了几个问题:

问题1.1. 证明 std::vector 在 $n$ 次操作的总时间复杂度是 $O(n)$ 的。

问题1.2. 小明发现如果添加很多元素之后删掉大部分元素,vector 内的的元素个数会远远小于容量,这很浪费内存。因此小明希望在元素太少时也重构,使得 $C$ 总是不超过当前元素个数的渐进线性。

小明仿照上述方法,规定在元素个数小于 $1/2 C$ 的时候就将 $C$ 变为原来的 $1/2$,申请一段新的长为 $C$ 的内存,并把原来的元素复制过去,释放原来的内存。

这种情况下,小明的 vector 在 $n$ 次操作的总时间复杂度是多少?

问题1.3. 做一些修改,实现问题1.2.中小明的想法,并且保证 $n$ 次操作的总时间复杂度是 $O(n)$ 的。

问题1.4. 小明发现虽然 $n$ 次操作的总时间复杂度是 $O(n)$ 的,但单次操作消耗的最大时间也是 $O(n)$ 的。小明希望减小单次操作的时间上界。有什么办法做到这一点吗?

提示:能否把重构均匀分配到之前的很多次操作里逐步进行,而不是在内存超过 $C$ 那一步一下子全部重构?

问题2. 小明听说路径压缩的并查集能够维护一些元素所属的集合并支持:1. 添加一个单点 2. 查询一个点所属集合 3. 合并两个点所在集合,但单次操作最坏是 $O(n)$ 的。

问题2.1. 现在有一棵 $O(n)$ 个点的并查集树(也就是说所有点都属于同一个集合,直接或间接连到同一个根),对每个点依次进行一次查询操作,没有合并操作。证明路径压缩的并查集在这种情况下的总时间复杂度是 $O(n)$ 的,无论查询顺序如何。

问题2.2. 小明发现某个并查集问题的操作有特殊性质:一共 $n$ 次操作,操作被分为 $k$ 轮:每一轮先进行 $a_i$ 次修改(操作3),再进行 $a_i$ 次查询(操作2),$2\sum a_i = n$。小明想要用路径压缩的并查集做这个问题,使得总时间复杂度仍然不超过 $O(n\log n)$ 的同时,每次询问的最坏时间复杂度(从读入这个询问到输出答案)都是不超过 $O(k)$ 的。

问题2.3. [经典问题,离线动态图连通性][P5787; LOJ121]有一个图,支持加边,删边,查询两点是否连通。一个经典做法是线段树分治,每条边的存在时间是若干个区间,这些区间共有 $O(n)$ 个。将这些区间放在一个以时间为下标的线段树上,对线段树进行遍历,进入/退出每个节点时执行/撤销这个线段树节点上区间对应的边(的连通性合并操作)。遍历到叶子时执行了的恰好就是这个时刻存在的所有边。

为了保证撤销的复杂度正确,一般用单次复杂度有保证的数据结构维护连通性,例如按秩合并的并查集。用路径压缩的并查集能不能解决这个问题?

问题2.4. 你能利用这种方式改进上述问题的时间复杂度吗? (参考答案-拓展阅读. https://www.luogu.me/article/asttym3k

AP006 前 k 小问题和最小扩展过程

问题1. 有两个长为 $n$ 的整数数列,问两个数列中各选一个数的所有方案中,第 $k$ 小的和是多少,$1\le k\le n^2$。请你设计出一个尽量高效的算法。

问题2. 有三个长为 $n$ 的整数数列,问三个数列中各选一个数的所有方案中,第 $k$ 小的和是多少,$1\le k\le n^3$。请你设计出一个尽量高效的算法。

提示:以下这个问题是困难的:

给定 $n$ 个值域较大(位数上界为 $\omega(\log n)$)的整数,问其中是否有三个数的和是 $0$。对于这个问题,人类目前没有找到任何时间复杂度在 $O(n^{1.999999})$ 的算法,也就是目前该问题时间复杂度的多项式次数不小于 $2$。这个问题被称为 3SUM

假如你有一个问题2的算法,你可能可以利用它设计出一个 3SUM 的算法,从而说明问题2的算法很难低于某个时间复杂度。

如果我们能说明在 $k$ 无约束的情况下问题是困难的,我们就知道了为什么总是考虑 $k$ 较小时求前 $k$ 小/前 $k$ 大,并且时间复杂度和 $k$ 有关。

问题3. 上次课程中已经给出了一个 $O(n+k\log k)$ 的问题2的算法,请你尝试总结该算法的适用范围和条件。你可以添加/删除条件看是否还能做。并解决这个问题:有 $n$ 个整数,请你求出前 $k$ 小的子集和。

问题4. [HDU5757]有 $n$ 个整数,每个整数被染成了黑白两种颜色,请你求出有偶数个黑色元素的子集中,前 $k$ 大的子集和分别是多少。

问题5. 有 $n$ 个整数,请你求出所有大小恰好为 $m$ 的子集中,前 $k$ 小的子集和。

问题6. [P2541]有 $n$ 个数列,每个数列长为 $m$,问每个数列中各选一个数的所有方案中,前 $k$ 小的和分别是多少。

问题7. 有 $n$ 个数列,每个数列长为 $m$,问每个数列中恰好各选 $c_i$ 个数的所有方案中,前 $k$ 小的和分别是多少。

并解决[P6646]。

问题8.[bonus] 根据以上问题,你能否改编或设计出一个需要用到类似方法的问题?

拓展阅读.[bonus] 一种不是保证从小到大扩展,而是类似迭代加深搜索的二分做法:https://www.luogu.com.cn/article/8lob9dt3

AP026 树上复杂度分析练习

问题1.1. 有一棵 $n$ 个点的有根树,每个点的权值等于自身的子树大小减去最大的孩子子树大小。所有点的权值和的上界估计是多少?

问题1.2. 有一棵 $n$ 个点的有根树,每个点的权值等于自身的子树大小减去前 $k$ 大的孩子子树大小。所有点的权值和的上界估计是多少?

问题2.1. 有 $n$ 个集合,每个集合初始大小为 $1$。你每次可以合并两个集合,设两个集合大小分别为 $a,b$,合并代价为 $\min(a,b)$,合并成一个大小为 $a+b$ 的新集合。所有集合最终合并成一个。分别估计最优合并顺序和最劣合并顺序对应的总代价。

问题2.2. 有 $n$ 个集合,每个集合初始大小为 $1$。你每次可以合并两个集合,设两个集合大小分别为 $a,b$,合并代价为 $a+b$,合并成一个大小为 $a+b$ 的新集合。所有集合最终合并成一个。分别估计最优合并顺序和最劣合并顺序对应的总代价。

问题3. 有 $n$ 棵字典树,且它们的点数总和为 $O(n)$,树的深度均不超过 $d$。合并两棵树的代价与两棵树交集的点数成正比,合并得到的为两个树的并集。所有树最终合并成一个,估计合并总代价的上界。如果把“点数总和为 $O(n)$”的限制加强成“字符串总长(所有叶子深度和)为 $O(n)$”,会有变化吗?

问题4. 有一棵 $n$ 个点的无根树,初始情况下每个点的颜色都是 $0$。$n$ 次操作,第 $i$ 次操作在树上选一条路径将路径上的点染成颜色 $i$。问:在操作过程中和结束后曾经出现过的不同的极大同色连通块种类数上界是多少?

问题5.1. 有 $n$ 个集合以及常数 $m$,每个集合初始大小为 $1$。你每次可以合并两个集合,设两个集合大小分别为 $a,b$,合并代价为 $O(a\cdot b)$,合并成一个大小为 $a+b$ 的新集合。所有集合最终合并成一个。分别估计最优合并顺序和最劣合并顺序对应的总代价。

问题5.2. 有 $n$ 个集合以及常数 $m$,每个集合初始大小为 $1$。你每次可以合并两个集合,设两个集合大小分别为 $a,b$,合并代价为 $O(\min(a,m)\cdot \min(b,m))$,合并成一个大小为 $\min(a+b,m)$ 的新集合。所有集合最终合并成一个。分别估计最优合并顺序和最劣合并顺序对应的总代价。

AP027 带权并查集练习

带权并查集:在并查集数据结构中,每个集合对应一棵有根树。我们可以在并查集树上维护每个点到根的信息,方法是维护每个点到并查集父亲的边信息,并在路径压缩时进行信息合并。

从集合的角度,可以认为带权并查集的权值是支持给某个集合整体加一个相同的值。

带权并查集通常用于维护原问题每个集合(连通块)内任取一点到其他点路径都足够使用的信息,例如二分图染色等。

带权并查集经常因为维护信息不能改变连边顺序,导致无法使用按秩合并。从给整个集合加操作的角度,这等价于操作的可逆性

问题1.1. [P1198]一个数列,要求支持向末尾插入一个数以及查询末尾 $L$ 个数的最大值,强制在线。请你用带权并查集解决这个问题。

问题1.2. 证明你在上个问题中的时间复杂度,并给出一个达到渐进上界的数据构造。(卡满你的算法时间)

问题2. [P2024] [NOI2001] 食物链。解决这个问题。另外,你做这个问题的并查集能同时使用路径压缩和按秩合并(启发式合并)达到 $O(n\alpha (n))$ 的时间复杂度吗?

问题3. [LOJ508弱化版] 你有一个 $n$ 个点的无向图和一个常数 $m$,有两种操作:添加一条连接 $(u,v)$ 权值 $w$ 的边,以及询问是否存在 $u$ 到 $v$ 的路径(可以是非简单路径)长度 $=x\pmod m$。

问题4. 类似离线 Tarjan LCA 算法的扩展,带权并查集可以用于计算树上路径信息。请你做这个问题:给定一棵 $n$ 个点的树,每个节点上有一个权值 $w_i$,请你求出给定的 $q$ 条路径形成的序列的最大子段和($n,q\le 10^6, w_i\le 10^9$)。

【欢迎投稿】有奖征集 OI 小知识点,思考题和科普,包括“广为人知”!

2025-11-07 18:38:48 By liu_cheng_ao

有奖征集 OI 小知识点,技巧和思考题,包括“广为人知”但大纲未收录的内容!

让所有重要的知识和技巧都“广为人知”,让所有偏门、鸡肋的知识和技巧都“物尽其用”。

投稿:发送至 oistars@qq.com 并同时回复本帖

本文在 LibreOJ 最新,不过所有平台均接受投稿!

核心规则

总述

有奖征集 OI 中大纲未收录的小知识,套路,技巧和思考题!包括你觉得“广为人知”或者不为人知大纲里没有的内容!

让所有重要的知识和技巧和你的优秀笔记都被推荐“广为人知”,让所有偏门、鸡肋的知识和技巧都作为思考题“物尽其用”。

征集范围为公开资料,可以直接推荐网络公开资料,也可进一步提供相关的笔记介绍、优质课件、例题、思考题等。撰写详细公开资料者以及发明/引入人有更多奖励

同一知识的推荐奖励先到先得。但对于详细公开资料作者,只要有新内容就有奖励,不受他人推荐影响。对于发明/引入人,奖励不受影响。

对于那些太细节/偏/杂/不实用的知识,可以造思考题。思考题分为 NOIP+ 和 NOI 两档难度,均有更高奖励。思考题比较类似大学算法课的思考题讨论,每个思考题围绕一个技巧/数学概念/动机等小套路展开,用于补足编程题不易表达的内容。思考题的例子可以参考:liu-cheng-ao.blog.uoj.ac/blog/9751

奖励内容为 现金+等额“星尘”(贡献分),会展示“星尘”前几名排行榜,可以选择匿名。多次贡献的同学可以加入在线文档和群方便查重交流。

  • 知识公开介绍推荐:最高 160 每个。
  • 知识公开介绍作者:最高 320 每个。
  • 思考题作者:最高 1024 每个。
  • 知识发明/引入者:最高 2048 每个。

鼓励投稿内容的投稿者自行公开传播其知识和文章。 去其它地方有偿投稿相同内容(有偿一稿多投)须事先明确告知双方并取得同意。

收集的知识列表会公开展示(审核、整理、展示等可能有延迟)。

收集的投稿内容会用在教材,题单,资源推荐等类型的公开项目同时也会用于训练课程

联系方式

  1. 同时详细内容/链接等及您的个人身份发送到投稿邮箱
    • 【邮箱:oistars@qq.com】 (旧邮箱 1525887403@qq.com 仍有效,但不建议发新内容)。
    • 您的网名,用于贡献榜展示,可以注明匿名。
    • 您的 OIerDB 个人页面,如果没有,可以写真实姓名+出生年份。用于发奖励。
    • 您的一个 QQ号,以便验证身份和后续沟通。
    • 您的个人信息不会被公开或传播给他人,除了贡献榜展示的网名外。
    • 您可以不提供个人信息,但没有信息将无法发奖励。
    • 即使您已经回复了本帖评论区也要发邮件。投稿时间以邮件首次发送完整内容的时间为准,细节可以后续勘误补充。
  2. 直接将小知识推荐和你的介绍/例题链接回复到本帖评论区。
  3. 我们会用邮箱回复您的投稿。
  4. 可以加入蔡德仁的 OI 教研群催促鸽子审核:群 QQ 435253885
  5. “星尘”(贡献分)达到 300 可加入征集讨论群 QQ 1061507046以及在线文档,便于讨论。

征集内容

在 OI 中的小知识,即常说的套路、技巧[tricks],和相关的笔记介绍、例题、思考题等。

  • 作为核心难点能出 $\ge 2$ 道不同 OI 题目的算法技巧、组合结构、数学模型、经典结论、算法方法等各种均为征集范围。
  • 不能是 NOI 大纲或大纲辞典明确收录过的内容。
  • 必须 OI 可做,不能过于偏/难,至少集训队得有几个人会或能立刻学会。
  • NOI 及以下难度的优先

征集形式

一、小知识推荐

  • 必须提供:较详细的介绍;或公开的介绍博客/资料链接。可以推荐其它人写的内容!
  • 可选提供:例题(需提供 题目来源链接或题意+题解)
  • 奖励:单个知识最高 160
    • 64(基础介绍)+32×(每道不同例题
  • 已有人推荐过的知识不计奖励,新例题仍计先到先得

二、详细笔记

  • 必须提供:本人撰写的一篇较详细的公开介绍博客/资料/课件,必须包含知识的详细介绍、思想、典型应用以及至少一道例题及题解。
  • 或者:本人创作的 OI 知识相关优质大众科普视频/文章
  • 奖励:单个知识最高 320
    • 基础 160。如果是第一个投稿该知识的详细笔记,则奖励至 320
  • 可以投稿在本活动开始之前创作的内容,但必须是本人撰写。
  • 重复知识,必须包含相对之前投稿的新内容。先到先得

三、思考题

  • 对于那些太细节/偏/杂/不实用的套路,可以用来造思考题。
  • 必须提供:思考题的详细题面和解答,以及核心知识。
  • 奖励:NOI难度 1024,NOIP+ 难度 512
  • 建议造之前先说思路,防止撞前面的题。和之前的思考题知识重复但仍有新内容的,奖励 256先到先得
  • 思考题的例子可以参考:liu-cheng-ao.blog.uoj.ac/blog/9751

四、发明/引入人奖励(特殊)

  • 必须提供:该知识的详细介绍资料/链接。以及本人作为该知识发明人/OI 首先引入人的身份和初期资料。
  • 奖励:NOI 及以下难度 2048,更高难度 1280
  • 发明/引入人奖励对大纲/经典教材收录的内容仍然有效

“星尘”(贡献分)

1奖励 = ¥1 + 1“星尘”(贡献分)

想要多参与的同学,“星尘”(贡献分)达到 300 后,可以加入在线文档和讨论群,快速查重交流。

其它

  • 如果你想推荐具体代码写法,请转代码细节征集
  • 如果你想推荐比赛注意事项,请转比赛注意事项
  • 如果你想推荐小资源,请转小资源合集
  • 如果你想推荐其它公开资源,请转网络资源推荐
  • 这些其它资源如果对 OIer 较有用,且您撰写了高质量教程,也可以同时邮件投稿获得 160 左右的奖励。邮件投稿时别忘了去对应的收集帖回复。

细则

本活动规则的最终解释权归主办方所有。

  • 在 OI 中的小知识,即常说的套路、技巧[tricks],和相关的笔记介绍、例题、思考题想法等。具体范围如下:
    • 作为核心难点能出 $\ge 2$ 道不同 OI 题目的算法技巧、组合结构、数学模型、经典结论、算法方法等各种均为征集范围。
      • 例子:bfs求常数边权最短路;贪心的邻项合并;单侧递归线段树;min-max 容斥;颜色段均摊;析合树;斜二进制倍增;分散层叠的多序列二分;01原理的排序分析;下标-值域-时间换维在数据结构上的应用;均摊分步化;折线图法分析括号序列和01序列;压位分块(四毛子在特定问题上的实现优化);Bostan-Mori;最优化推式子技巧(例如 $\max(\lvert x\rvert)=\max(\max(x,-x))$);完全图zig-zag构造技巧;基于 Farey 序列的 $O(1)$ 在线查询逆元;矩阵乘法的常见 OI 归约;……
      • 下至 CSP-J 上至 NOI+ 难度都可以!
      • 这些已列出的例子如果你能提供好的例题,仍然有奖!
    • 不能是《NOI 大纲》《NOI 大纲辞典》明确收录过的内容
      • 你也可以投稿教材目录提到过的内容!
      • 例外情况:如果是作者/引入者本人领奖,不受限制。
    • 必须 OI 可做:
      • 必须是算法/计算机内容且能出 OI 题。
      • 不能是 OI 未引入过的偏僻论文、科技。(大致标准:假设给现役集训队统一讲解该知识 5 分钟,然后出 OI 题单独作为集训队测试,能有 4 人以上在 5 小时内 AC。)
      • 优先征集 NOI 难度以内可考的知识。
  • 奖励:
    • 一、小知识推荐
      • 之前有人推荐过的知识不计奖励。
      • 之前有人推荐过该知识,但你提供了新的例题的,只计算新的例题奖励。题意足够类似的例题算一道。仍然受单个知识上限限制。
    • 二、详细笔记
      • 可以投稿在本活动开始之前创作的内容,但必须是本人撰写。
      • 如果是重复知识投稿,必须包含相对之前投稿的新内容才计算奖励,如更易懂的解释,新的理解视角,或新的例题。
      • 同一人只能对同一知识奖励一次。
    • 三、思考题
      • 同一人只能对同一知识奖励一次。
    • 四、发明/引入人奖励
      • 发明人和引入人是不同人的,独立计算奖励。
      • 发明人或引入人是多人共同的,共同计算奖励。
      • 同一人只能对同一知识奖励一次。

个人著作权声明:严禁任何未经本人(刘承奥,常用笔名/网名:蔡德仁 CommonAnts LCA liu_cheng_ao)书面授权者在梦熊联盟,或者任何虚假宣传或不实营销炒作或不正当竞争行为严重的 OI 机构的课程内或交流平台(包括但不限于品牌集训线下讨论,交流群,OJ,公众号,视频号等)上引用、传播、讨论此内容,以及本人于2024年5月及之后发布的所有内容,包括声明为公开的内容在内。

之前已发布的本文草稿内容:https://www.luogu.me/paste/gzsaf4gu

2024年及更早的本人同类计划:https://pqsyrcnk3fo.feishu.cn/wiki/Xk79wgM8uiBQGRk6x6TcueXznaf

坚决反对打着“公共资源”旗号鼓吹“稀缺性”,妄图商业垄断的行为!

坚决反对打着“公共资源”旗号进行商业炒作营销,剽窃公开资源开设付费课程坑骗家长和学生的行为!

坚决反对与虎谋皮,以营销炒作的方式“推广知识”,破坏社区秩序的行为!

坚决反对通过向部分不懂算法的家长/教练危言耸听,吹嘘特定知识重要性,强迫学生学习,破坏教学秩序的行为!

坚决支持建设高质量公开资料推荐平台和刊物平台!

【欢迎投稿】OI 教学研究当前的若干具体问题:行动起来!

2025-11-04 14:39:31 By liu_cheng_ao

个人著作权声明:严禁任何未经本人(刘承奥,常用笔名/网名:蔡德仁 CommonAnts LCA liu_cheng_ao)书面授权者在梦熊联盟,或者任何虚假宣传或不实营销炒作或不正当竞争行为严重的 OI 机构的课程内或交流平台(包括但不限于品牌集训线下讨论,交流群,OJ,公众号,视频号等)上引用、传播、讨论此内容,以及本人于2024年5月及之后发布的所有内容,包括声明为公开的内容在内。

如果您想提出问题或建议,敬请留言!

OI 教学研究当前的若干具体问题:行动起来!

以下分章节列出笔者了解的OI教学研究亟待解决的,当前的若干具体问题。每个问题分为当前背景,问题概括,笔者个人思路(抛砖引玉)几部分。

教学资源问题

公开资源推荐/摘要问题

公开资源是 OI 最好的成文资源。 基本上,OI 的付费/私有资源仅有高水平同学(教师同理)和教学管理是公开资源无法代替的。对于题单模拟赛等情况,公开资源经筛选后的质量普遍比私有资源更高。但是公开资源缺乏整理。

问:公开资源缺乏整理,如何整理一些平均质量高,总量精简的公开资源供教学/自学使用?

个人思路(抛砖引玉,下同): - 由笔者等全职/半全职的高水平教研人员进行一个长期示范性的筛选项目。 - 鼓励广大 OIer 进行自己的筛选。 - 鼓励广大 OIer 进行推荐投稿。 - 对广大 OIer 的工作进行物质上和社区上的激励。 - 可以分类为入门/家长,普及,提高,进阶四个组。每个组的标准和宣传策略不同,但应该互通。 - 总的原则应该是少量高精,适合自学。 - 很多教练特别是经验丰富的老教练也做了工作,应该特别注意前辈的贡献。尤其是在入门阶段!

教材问题

缺少主干教程/教材。它应该是可自学的。刘汝佳,CCF中学生计算机程序设计系列,一本通系列等教材较过时。具体来说: - 入门:笔者教学水平和对入门学生的认知不够评价这个的,不过有不少教师研究,成果尚可。缺乏筛选和宣传推广。 - 普及:洛谷的书尚可 - 提高:洛谷的书和李老师《算法竞赛进阶指南》尚可 - 进阶:空白 (笔者当前主要工作) - 数学前置知识:缺乏 有一些教练编的书,但水平有限

问:入门和普及书缺乏筛选和宣传推广,进阶教材空白,数学前置知识教材缺乏,怎么做?

个人思路: - 笔者主编一套进阶教材书,涵盖进阶知识中所有基本方法和大知识点/常见技巧,并兼顾某些金牌选手继续对接学术界的视角需求。 - 鼓励广大 OIer 多写算法技巧和数学前置知识笔记总结,并收集编修推荐。 - 对广大 OIer 的工作进行物质上和社区上的激励。

社区问题

社区组织问题

有很多 OIer 对 OI 社区本身感到迷茫,这阻碍了分享和交流。OI 社区需要一面旗帜来作为坚强的希望。

问:如何让 OI 社区更加组织起来?

个人思路 - 首先,OI 社区要组织起来的办法有且仅有一个,那就是在不断解决 OIer 自己的具体问题的过程中达到。 - 不是整个 OI 社区需要被组织,而是社区中希望做一些工作的 OIer 会想要一个组织,学习生活中感到孤独的 OIer 会呼唤一个组织。 - 需要有人在清华北大/集训/强校附近等 OI 社区核心人员集中区域进行联络,维持 OI 社区的讨论,并且通过游戏、茶话会等方式联系大家。笔者预计在每年 3 到 6 月的春季学期常驻海淀。 - 可以先推进教材、公开资源推荐、刊物等同学们最关注最需要的事情,达到一个阶段。 - 需要研究出如何有效地进行物质上和社区上的激励。光是发钱不行。 - OI 有没有类似“街坊邻里送锦旗”那种有效的群众之间能自发进行的夸人方式?(也许发展一下徽章交换?) - 发展 OI 民间公开奖项!应该搞几个年度好题奖,年度好文奖等。 可以以各大公开 OJ 管理组、刊物编辑部为核心结合群众投票来搞。可以背靠清北等大学进行提升获得感。 - 能不能让 CCF 或者大学搞点激励? - 包括一些乱象和乱搞的机构在内,外部压力也会促使 OIer 不得不在某种程度上团结起来。

报刊问题

洛谷日报停办后,包括洛谷专栏全站推荐在内的报刊类平台流量较低,起不到真正加强交流,推广宣传优质资源的作用。最近还发生了有 OIer 被逼到营销炒作的闹剧。应当解决这一需求。

问:如何办一个报刊,加强 OIer 的交流并推广宣传优质资源?

个人思路: - 笔者联系组织一个电子周刊,初期内容类似升级版本的洛谷日报,分为多个栏目。初期内容可以少,乃至不同期轮换不同栏目,但一定要以周刊频率更新并保持宣传。 - 接受投稿并且主动联系具体 OIer 个人征稿。 - 可能的栏目: - 知识/技巧讲解 - 好题推荐和题解 - 杂谈杂文 - 入门/趣味科普(非常重要!) - 教师讲谈(可以请一些关心 OI 发展的年轻教授等) - 公开项目和高质量资源推荐页(每期必备) - 独立广告页(筹集经费和团结正常机构学校等)(每期必备) (广告页不属于正文,而是单独的图感谢支持。向家长,教练等推送时由推送者个人附带发送。) - 其它……(请大家集思广益提建议) - 每一期在洛谷、UOJ、QOJ、LOJ 等大公开 OJ 全文发送,并允许正常机构转载。 - 直接推送给各大 OJ 群和网上活跃的选手。 - 直接推送给各大教练和学校。 - 大量制作切片、梗图等在家长群、公众号、自媒体等一切平台大力传播,扩大影响。 - 为了筹集经费和团结正常机构学校等,必须有广告页,但必须保留独立性和每期的接收权。拒绝一切劣质机构。 - 应该进行大项的财务公开,但不要被舆论绑架去公开不适宜内容。 - 通过 CCF/科协和清华北大及其中个人等,获取合规资源和名号(最好有网版号,或 NOI 冠名等)。当然,具体内容事务都要由 OIer 负责。

鸽子复活/鸽子起飞问题

OI 经常有同学搞很多好的项目,但随着创始人的忙碌升学等很多都渐渐废弃。应该恢复和发展这些现成的好资源,达到事半功倍的效果。例如 OI-Wiki,Public Judge,退役OIer文化课交流群等。除了鸽子,也有很多萌芽状态的好项目类同需要支持。

问:如何恢复和发展这些鸽子项目/让新鸽子起飞?

个人思路: - 这些项目主要是缺乏人力,而且技术要求极高,必须恢复核心人员或找到后继。需要调查研究每个项目核心成员的具体情况。 - 根据一些了解,OIer 对此类资源普遍的抽象讨论和跟风差评等造成了严重影响。做社区心理建设时应该特别做好拥护高质量公开资源的工作,也应该在 OI 建设过程中让 OIer 达到团结。 - 也许可以给资助? - 也许可以和大学合作挂点项目? - 也许可以有人去清北或者某些 OI 社区核心人员聚集地(尤其是高中生的)经常联络,推大家干活并且组织一些欢乐活动?对于一些强校,可以考虑在当地找一些成熟的学生或者教练负责。 - 很多教练特别是经验丰富的老教练也做了工作,应该特别注意前辈的贡献。推广和改进它们的质量。尤其是在入门阶段!

讨论群摘要问题

OI 有很多高质量资源的来源是讨论群,比如 UOJ 群消息记录。应该搞一些 AI 消息摘要总结出其中有价值的内容。

问:如何做讨论群消息摘要?

个人思路: - 已经有人干了,支持他们。类比鸽子起飞问题。

提问平台问题

OI 是不是需要一个 OI StackExchange?优点是便于搜索问题和提问。

问:OI 是不是需要一个 OI StackExchange?

个人思路: - 目前来看没有其它问题紧急,也许周刊办起来之后会看到究竟是否必要。 - StackExchange 类讨论平台需要的社区人数远大于讨论群,特别是需要某种专业态度,OI 难以支撑。 - OI 更合适的还是比较市井的讨论群:群灌水无法避免,只是对我们来说讨论问题是灌水的一部分。选手水平高了自然也就讨论得了更难更深入的内容。 - 因此个人认为上面的讨论群(AI 摘要弥补不能积累、搜索的短板),加上报刊,以及 OJ 讨论区,比开 StackExchange 更好。后者看不到维持方法。

应用开发问题

原题机问题

所谓原题机就是给出题意,搜索推荐原题和高相似度题的搜索引擎。现在已经有了几个基于 LLM 的原题机项目,比如 yuantiji 和 CPRet。但现在只能做到搜题面相似的,模型能力和微调都较差,也没有利用好问题的题解,标签,程序等数据。还做不到搜想法或简要题意等。

问:如何推动原题机开发?

个人想法: - 在鸽子问题的基础上帮助现有项目继续推进,需要经费。但应该不多,百万级别即可。其它事情初具规模后可以资助此类项目。

造题平台问题

目前有一些造题平台。比如 polygon,tuack,乃至较新的 hull 等。但是他们技术上虽然足够使用,可是学习门槛高用户体验较差,不太适配一般用户和教练之类的使用需求。用户体验不好就没法以程序自然而然培养用户习惯,从而推广大样例等规范和降低错误。

问:如何开发一个高用户体验的造题平台?

个人思路: - 在鸽子问题的基础上帮助现有项目继续推进,需要少量经费。十万级别即可。另外还需要一个懂用户体验且懂 OI 的产品经理,这个暂且不知道。

AI 辅助教学问题

随着 AI(目前主要是 LLM 路线)的能力发展,应当且必须研究开发 AI 在教学中的应用。不能指望大机构,商业决定了他们的开发主要是 AI 读稿降本增效,而不关心实际效果。

问:现在应该开发哪些具体的 AI 辅助教学方式?

个人思路: - 应该推动 AI 资料查找在教学中的使用。 - 应该推动 AI 思维链在教学中的使用。 - 应该推动 AI 辅助编程/调试的实用化,但不能整体替代,最好达到学生平时写代码框架用 AI 辅助完成机械工作,模拟赛完整自己写的状态。 - 应该在现有大型 OJ 中引入高质量的 AI 推荐等系统。 - 应该按照鸽子问题支持已经存在的这类项目。

OI 和 OIer 发展问题

社区心理建设问题

OIer 在平时孤独学OI的迷茫中积累了大量心理压力,并且承担着巨大升学风险、不被认可的社会压力等。抽象卖弱等是普遍情况。如何对待?

问:如何进行社区心理建设?

个人思路: - 充分尊重 OIer 压力巨大的现状。将外部压力分为心理环境的困难(比如 OI 受歧视,OI 社区搞抽象卖弱带来的压力)和硬困难(比如个人家庭问题或升学压力)两个部分进行考虑。 - 在 OI 社区中建立机制降低 OI 社区本身带来的问题,尤其是减少 OIer 向其它 OIer 发泄形成的恶性循环。(参考上面的社区组织问题。) - 对于硬困难,一方面减少困难,一方面组织互助(比如退役OIer文化课),一方面介绍社会具体情况,并找前辈进行交流,打破神秘幻想。对于个别事件进行具体帮助。 - 用成文的娱乐代替碎片的娱乐。不要完全禁止打游戏,但坚定推进游戏和聊天代替短视频,发展多人游戏和线下游戏/运动。 - 坚决支持和帮助学校教练这一重要力量。 - 向家长传播现状事实和正确观念有利于家庭和谐。

集训队发展问题

集训队选手脱离 OI 的一部分中,有迷茫不知所为的问题。留在 OI 的一部分中,有继续学习算法/计算机和对接学术界的发展问题。总的来看,问题是周围人不能真正的理解集训队选手的情况,没有专业的讨论和指导,看不到未来的道路。尤其是初中集训队水平选手情况极其严重。“上午卖弱,中午颓废,下午鱼鱼,晚上抽象。”成为普遍情况。

问:如何推进集训队发展?

个人思路: - 对于高二学生,继续建设大学预科。 - 对于低年级学生,作为前辈多交流,并且可以找关心 OIer 发展、专业水平过硬的大学教师/从业人员等,多组织对话研讨等活动,破除对未来的无知状态。这一对话形式也可以有较为普及化的版本,见报刊问题。 - 可以发扬 UOJ 群这样前辈较多的交流作用,并发展上述交流人员的讨论社区(群?)。 - 适当找事干,例如跟前辈学习某些学科分支、建设 OI 社区、其它计算机兴趣、发展个人爱好等。 - 青少年的迷茫和不知道做什么是正常情况,应当在参与各种具体的学科分支和具体接触各种事物过程中考虑。不要太急,“玩”两年绝不是浪费时间! - 坚决反对拿低年级学生炒作甚至交易的行为!

退役OIer文化课自学组织和自学资源开发问题

OIer 退役后有学文化课(乃至大学学习以及自己想学习的内容)需求。应当发扬 OI 社区的优点,对文化课乃至一切学习人数多的科目都进行教研,分享公开资源建立社区。

问:如何推进中学文化课/大学的自学社区发展?

个人思路: - 学习方法是共通的,而且 OIer 的自学能力和理解能力普遍足够。OI 有组合模型、推导、算法技巧;文化课也有问题套路和二级结论。完全可以用类似方式分享公开资源,例如笔者公开资源推荐中的范例。 - 结合该领域原本的自学资源。例如大学计算机的 csdiy.wiki,文化课的笔袋(@一数)等。 - 如鸽子问题,推进退役 OIer 文化课交流群等的发展。 - 长期来看,OI 社区的好的自学组织经验输入其它领域,将会促进普遍教育的普惠发展。

OIer 的非 OI 计算机兴趣发展以及兄弟组织的协作问题

目前 OI 仍然承担着大量仅仅是对计算机感兴趣或者仅仅是不想学文化课的学生,处于转型时期。许多 OIer 有转向非 OI 的其他计算机专业方向的兴趣和需求。另外,这几年蓬勃发展的新高考信息、少儿编程、大学本科计算机课改、CTF、LLM竞赛等也都需要 OI 的经验支持。

问:如何推进 OIer 的非 OI 计算机兴趣发展?如何推进兄弟组织的协作?

个人思路: - 对于大学本科计算机课改、CTF、LLM竞赛等兄弟项目,应当鼓励有志的 OIer 在中学毕业后进行参与,并有意建立与 OI 的联系,用 OI 的经验支持之,与其中具体的学生和教师紧密团结。 - 对于新高考信息、少儿编程等基础教育普及活动,OIer 毕业生将是师资的中坚力量,应当在这些领域建立学习和自学的资源协作,并用 OI 的经验支持之,与其中具体的学生和教师紧密团结。 - 个人发展的其他方面参考集训队发展问题,主要还是找前辈破除未知状态。

教练学习问题

目前有许多教练实际上有提高自己教学水平的愿望和时间投入。如何让他们学习更有效?

问:如何让愿意提升教学水平的教练高效学习?

个人思路: - 学习方面是和学生类似的,但不需要写太多代码。 - 能够自行搜索的时间更少。因此,刊物和教材如果能够办成,有很大效果。 - 能否同时发展 CCF 的教师培训? - 个人想法较少,恳请各位集思广益。

科学传播和推广问题

科普问题

目前已经有不少 OIer 在视频网站等地做科普。怎么帮助他们做得更好?

问:如何帮助 OIer 的科普做得更好?如何推广传播?

个人思路: - 完整的科普较多发在个人博客或中长视频站等平台。 - 科普水平主要来源于教学水平,特别是教研和学习方法。因此提高 OI 水平的教研和学习方法就是主要途径。大家学会学习,学会做笔记就是学会讲。 - 可以同时鼓励一些非 OI,非算法内容。 - 可以在刊物中推广。可以办奖。参考社区问题。 - 要兼顾选择一些热门的具体入门问题进行科普。革新派科普的重点在于讲好一个简单和吸引人的问题,传播科学精神。不要贪大求难。 - 短平台传播参见入门与家长传播问题。

入门和家长传播问题

目前家长中,尤其是入门级别(含少儿编程),充斥着大量营销号和垃圾信息。缺乏好的科普和入门资料以及传播。

问:入门和家长传播问题怎么办?

个人思路: - 制作一些精简而专业的入门资料(例如学习阶段、考试注意事项、热门问题讲解等),以一图流、切片等方式,在学校、家长群、公众号、短视频、图文等一切平台猛烈地传播,并且附加公开资源以及有高质量课程的地址。(这是必要的,因为必须解决家长需求。) - 不要怕丢脸,不要怕被骂,到群众中去。不要有顾虑,不要因为不敢带水印、不敢带课程链接、不敢蹭热度、不敢碰瓷指出错误,束手束脚反而忽视家长的实际需求。只要有立锥之地,即使一开始只有百分之一的家长相信,营销号就不能为所欲为,他们为了流量也就不排斥讲些真话。 - 宣传稳定后,可以由部分可靠人员办一些超低价基础课程,通过极大扩张人数的方式降低价格。这类课程实际类似录播课,质量受限制,可以倒逼各个机构“产业升级”做高质量课程。OI 社区本身应该仍然保持严格的完全公开和非商业,不能有商业关系,不能自己办,以免遇到洛谷“不完全商业化”的挫折,以及避免被腐化的风险。 - 参见报刊问题。

中小学推广问题

目前很多学校有搞 OI 的需求,主要是新开始或者 NOIP+ 的需求。学校需要包装完整简单的解决方案,以及政绩,和经办人员的个人利益。应当和劣质机构竞争学校。

问:OI 社区可以怎样向学校推广优质资源,打击劣质资源和不正当竞争?

个人思路: - 向各个学校和教练直接推送高质量公开资源,例如周刊。 - 对公开资源进行完整包装,傻瓜式使用。公开资源开发也要考虑用户体验。 - OI 社区包括刊物等不参与直接的商业行为,通过分散公平地接受多家正常机构广告,忽视劣质机构,引导有需求的学校选择业务。OI 社区本身应该仍然保持严格的完全公开和非商业,不能有商业关系,不能自己办,以免遇到洛谷“不完全商业化”的挫折,以及避免被腐化的风险。

个人项目地址

结语

OI 作为算法和计算机科学的自学社区,OIer 作为自我发展的群体,已经在过去的历史中创造了:不长期依赖高校教授等外部教育资源,二十年做出最好的算法与计算机基础教育、本科教育和基础研究生教育的人间奇迹。这是同学们的胜利,是 OI 社区的胜利,是竞赛这一自学组织政策的胜利。

现在,OI 已经发展到不再能从学术界获取现成答案,必须进行教学研究的阶段。近几年以来,广大 OIer 无私奉献,分享知识,以科学精神反思研究学习过程,拥抱新技术,产出了大量教学研究成果,变教学无用为教学有用,变资源壁垒为资源共享,使 OI 取得了现在的伟大进步。

现在,从少儿编程到中学课堂,从集训机房到 OI 赛场,营销猖獗,欺骗泛滥。OI 不可能在浪潮中独善其身,必须主动拥抱广大入门学生及家长的需求,才有可能为自己争得良好的环境。

现在,同学们有了各种各样新的需求。现在,OIer 不仅包括 OI 社区讨论核心,同样包括入门学生,退役选手,关心教学的教练。乃至是大学教师和 NOI 科学委员会中一切推动 OI 的高质量、普惠学习的人

我们应当自觉起来,我们应当立刻动手解决自己的问题,我们应当响应同学们和家长们对我们的期许和召唤。

我们应当响应政策的号召,利用好一切有利的环境,发挥我们在大中小学的人和资源,包括 CCF 中具体的助力,在保持公开和独立的同时团结广大合理运营的机构。

我们应当利用切片、公众号、自媒体等一切新的手段,使用学校、教授和 CCF 等一切可以获得的支持,向广大(特别是入门和少儿编程)家长和学生广泛公开地宣传高质量的学习资源,正确的学习方法和 OI 乃至整个少儿编程和大中小学计算机教育的真实现状。不要怕丢脸,不要怕被骂,到群众中去。只要有立锥之地,即使一开始只有百分之一的家长相信,营销号就不能为所欲为,他们为了流量也就不排斥讲些真话。

对于合理运营的机构和其他组织,我们应当在保持自身独立性的同时与他们中愿意提升具体教学质量,宣传正确观念,不搞不实营销炒作和不正当竞争的项目、人员及部门紧密合作。促使他们在机构内的权力巩固,压制传销派别。

对于那些严重虚假宣传,严重不实营销炒作,严重不正当竞争,严重欺骗家长学生和学校,严重破坏 OI 社区的机构和行为,不仅要坚决彻底地揭露和反对,还应该向他们的受害者宣传和提供真正优质的公开资源。这些在金钱面前胆小怕事的人,就不得不有所收敛,不得不讲些真话了。

对于升学或竞赛政策的推进等,我们从具体的事做起。能动的具体问题要动,能说话的机会要说。对于具体学生,一方面是指明中学毕业后未来的发展道路,协助 OIer 了解社会的具体情况,联系认识相关人员,破除所谓“社会”的迷雾和神秘的幻想。另外,对中学生特别重要的一点,是在文化课等学习发扬 OI 的长处。OI 可以总结推导和技巧,文化课没有道理不能总结方法和二级结论,并以 OI 社区的方式产生公开资源进行互助。

向科学和普惠的教育前进!

如果您想提出问题或建议,敬请留言!

【欢迎投稿】一文概括所有比赛注意事项,以及同类资料推荐

2025-10-31 22:04:47 By liu_cheng_ao

大部分文章在我的 LibreOJ更新,其他平台可能更新不及时,但你仍可以在其他平台投稿征集内容和建议。

个人著作权声明:严禁任何未经本人(刘承奥,常用笔名/网名:蔡德仁 CommonAnts LCA liu_cheng_ao)书面授权者在梦熊联盟,或者任何虚假宣传或不实营销炒作或不正当竞争行为严重的 OI 机构的课程内或交流平台(包括但不限于品牌集训线下讨论,交流群,OJ,公众号,视频号等)上引用、传播、讨论此内容,以及本人于2024年5月及之后发布的所有内容,包括声明为公开的内容在内。

使用这些建议时请确保你理解其内容,由于使用这些建议造成的问题与本文作者无关。

如果你有自己熟悉的代码习惯,考前不要变更自己的代码习惯!这个优先级高于一切!可以考完后花一个月慢慢适应好的写法。本文也不是唯一答案,如果你习惯你自己的策略,那就不要改,参考一下细节即可。

省流版

包含下述所有内容的摘要:

  • 在平时模拟赛就学会并习惯比赛策略,命令行用法,对拍等内容!
  • 考试须知 身份证,准考证,别迟到,收手机,考场纪律啥的。请看:官方提供的考试须知。
  • 比赛策略
    • 前 15% 时间读所有题并想所有题,然后开始写最高的分以及调试,最后 5 分钟检查
    • 看题一定要逐词看过去,包括封面和提示。读完题先手算小样例确认理解。
    • 先看完所有东西,再想过所有东西,最后写东西。
    • 每几分钟(或喝水,伸懒腰)提醒自己是否发呆,发呆立刻切换
    • 先写得分性价比高的,性价比相近时先写短的(比如暴力)。
    • 先写程序框架,每段大致含义,关键内容的原问题精确数学意义,后填代码。
    • 有时间要对拍
    • 要写部分分
    • 别怀疑别人比自己强/自己是弱校弱省/做不出题怎么办,至少你看的这个指南是最强的老师写的不是吗?
  • 编程注意事项
    • 与其去背易错细节害怕记漏,不如养成好习惯消除错误风险!
    • 缺头文件 问:头文件打少了爆零怎么办?
      • 答:#include <bits/stdc++.h>
    • 命名冲突 问:自建变量 y1 next pipe 等和标准库重名爆零怎么办?
      • 答:namespace 包裹自己的程序
    • 少用宏 问:#define 让我爆零怎么办?
      • 答:非必要不用宏,用 using 和函数等代替。
    • 编译器帮你查错 问:函数没返回值/隐式类型转换出错/重名变量等查不出怎么办?
      • 答:添加编译选项 -Wall -Wextra -Wconversion -Wshadow 让编译器帮你检查。
    • 调试工具 问:有什么工具帮我查运行错误/下标越界/数值溢出?
      • 答:调试时按需求添加编译选项 -g3 -fsanitize=address,undefined -D_GLIBCXX_DEBUG 等并使用对应的 gdb asan 等工具。
    • 忘改调试/注释 问:调试的时候注释了 freopen 忘记恢复/忘删调试语句爆零?
      • 答:采用宏 #ifdef MYDEBUG,不要注释。
    • 输入输出优化 问:用什么输入输出?要读入优化吗?
      • 答:平时用关同步 cin/cout,量巨大时用 cin.read() cin.gcount()/cout.write() cout.flush()
    • 开栈空间 问:我本地测试怎么开大栈空间?
      • 答:Linux(含 NOILinux)在终端运行程序前先运行指令 ulimit -s 1000000,Windows 编译选项添加 -Wl,--stack=1000000000
    • 测时间和内存 问:如何测自己程序时间和内存?
      • 答:Linux 用 time ./程序名 测时间,ulimit -v <内存限制KB数> 测超内存限制。Windows 用程序内 clock() 测时间,用命令行 cmdsize 测内存。
    • 考试环境是 Windows 问:考试环境是 Windows 怎么办?还有前面没提到的吗?
      • 答:务必打开显示文件扩展名。
    • 不要写超标语法 问:用超标/被禁语法爆零了怎么办?
      • 答:平时就别写超过 -std=c++14#pragma 之类的违禁品。

防爆零指南之:考试须知和考前准备

  • 在平时模拟赛就学会并习惯比赛策略,命令行用法,对拍等内容! 临时抱佛脚可翻到本文最后一部分的推荐文章。
  • 身份证,准考证,别迟到,收手机,考场纪律啥的。请看:官方提供的考试须知,以及考试现场通知。
  • 试机一定要试机器,有问题找监考不要自己修电脑,监考水平差不要惊慌,不要顶撞。试机器特别要注意键盘鼠标功能,开关机不还原的区域等。Windows 的话还得注意找编译器路径考试的时候设置环境变量方便 cmd

防爆零指南之:比赛策略(如果你有自己熟悉的习惯和策略,那就不要改!)

要点:

  • 前 15% 时间读所有题并想所有题,然后开始写最高的分以及调试,最后 5 分钟检查。 如果你没有一个自己的非常明确的策略建议这个。检查包括关闭代码编辑器,用题面说的编译选项编译代码,测试样例输入输出正确(特别注意不能有调试输出),检查文件名、文件夹格式等,检查期间和之后不要打开代码文件以免误触。
  • 看题一定要逐词看过去,包括封面和提示。读完题先手算小样例确认理解。
  • 先看完所有东西,再想过所有东西,最后写东西。 不要先写第一题后看第三题。读题的时候除了你能立刻流畅想下去的做法继续想,一旦卡一点就记下来,不要强行想。先看完后面的题,对所有东西有个整体把握。同理,开局第一小时还有题没想过的情况下,会做题了也不要急着写,先记下程序框架和关键变量的意义,然后先想想其他题。
  • 每几分钟(或喝水,伸懒腰)提醒自己是否发呆,发呆立刻切换。(上厕所调整,换大思路,写其他题等)避免浪费时间。不要一直死磕想/调一个题。
  • 先写得分性价比高的,性价比相近时先写短的(比如暴力)。 得分性价比是脑内大致估测的得分除以预计写代码时间,别花时间估计,有个印象就行。
  • 先写程序框架,每段大致含义,关键内容的原问题精确数学意义,后填代码。 可以用注释写。内容含变量、数组、类型、函数等,要精确到 $f[i]$ 到底是考虑了 $\le i$ 还是 $\lt i$ 的状态。这样可以解决自以为会了但没想清楚的,调试的时候也可以逐段对比反例找到错点。
  • 有时间要对拍。 另外写的暴力也能帮你得部分分,打表找性质等。有时间就枚举所有小数据(能测边界情况)+测试极端数据。没时间对拍就手算几组小数据和小边界。
  • 要写部分分。 时间多又不会写更高分,且对拍写完时,尝试写乱搞。

详情请看课件:《如何打比赛.pptx》《编程基础:设计,测试,调试.pptx》。(我目前没地方放公开文件,暂且可以加我的QQ群 435253885。UOJ 群也发了如何打比赛。欢迎各大 OI 群(除了声明中的机构群)和各位老师同学转载。)

防爆零指南之:编程注意事项(如果你有自己熟悉的习惯和策略,那就不要改!)

与其去背易错细节害怕记漏,不如用好习惯消除错误风险!

缺头文件

问:头文件打少了爆零怎么办?

答:#include <bits/stdc++.h>

详情:竞赛官方使用的编译器 GNU-GCC-G++ 提供的 <bits/stdc++.h> 包含了 C++ 所有的常用标准头文件(除了竞赛不涉及的新版内容外)。打竞赛时养成用且只用 #include <bits/stdc++.h> 的习惯,平时打竞赛也不要用 <ext/pbds> <windows> <dev/random> 等非标准内容。特别注意头文件里的斜杠是正着 / 不是反着,否则 NOILinux 会编译错误!

命名冲突

问:自建变量 y1 next pipe 等和标准库重名爆零怎么办?

答:namespace 包裹自己的程序

#include<bits/stdc++.h>

using namespace std;

namespace my_namespace{
    // 我的程序
    int main(){
        // 我的程序
        return 0;
    }
};

int main(){ return my_namespace::main(); }

这样就会优先读你定义的名称,不会因为库函数重名错误。另外,不要用宏 #define 改名字

少用宏

问:#define 让我爆零怎么办?

答:非必要不用宏,用 using 和函数等代替。

宏是在代码文字层面的操作,会有各种意想不到的错误。

例如: - #define M(x,y) x=(x+y)%mod 然后 M(a,n>>2); 会变成 a=(a+n>>2)%mod;,然后 + 的运算优先级高于位运算,a=((a+n)/4)%mod;,爆零。 - #define lowbit(x) ((x)&-(x)) 然后 lowbit(f(n)) 会导致函数 f(n) 被调用两遍,复杂度和副作用都爆了。 - #define 和标准库冲突的名字,能穿透所有 namespace 直接让你爆零。 - 忘记加 #undef 导致后面都错了。

除了 #ifdef 包裹调试语句之类的必要情况,或你非常熟练的模板,都不要用宏!即使是必要情况,也一定要加对应的 #endif #undef 等,并且尽量别用括号里有参数的宏!

危险程度:反复改代码 > 用宏 > 用其他语法!

常见替代方案:

  • #define int long long:用 using ll = long long; 代替(不要改 intll 之类的简写就行),以及代码编辑器的查找替换功能代替。
  • #define lowbit(x) ((x)&-(x)):用函数 int lowbit(int x){return x&-x;} 代替。现在都有 -O2,这不会变慢!
  • #define endl '\n',用了自己的命名空间后,你可以在 my_namespace 里定义 const char endl='\n';
  • 局部复用代码片段(例如写双指针复用指针移动操作):使用函数、lambda 表达式等代替。(平时不熟悉的不建议用 lambda)

编译器帮你查错

问:函数没返回值/隐式类型转换出错/重名变量等查不出怎么办?

答:添加编译选项 -Wall -Wextra -Wconversion -Wshadow 让编译器帮你检查。

  • -Wall 警告很多东西例如未使用的变量,未初始化的变量,%dlong long,if-else 嵌套不写大括号有歧义等。
  • -Wextra 额外警告一些东西。
  • -Wconversion 警告隐式类型转换的问题,比如 intunsigned int/size_t 比较会导致 -1 > 0u 乃至 vector a; for(int i=1;i<=a.size();i++); 死循环。
  • -Wshadow 警告局部和全局,内层循环和外层变量同名。
  • -fno-ms-extensions 关闭一些和微软编译器一致的特性,比如不标注返回值类型的函数。只有 Windows 需要,Linux 的默认就有。
  • 开多了会有很多警告,编译信息太长翻不完,建议给编译命令最后添加 2> log.txt 重定向编译信息。以免其实没错还在虚空调试。Linux 也可以在编译命令最后再加 && echo ok,这样编译成功包括无错误只有警告时也会最后输出 ok

除此之外还有 -Wformat=2 更严格检查格式化字符串(但建议直接用 cin/cout),-Wpedantic 检查非标准代码(比如 (Node){u,v,w}),等其它查错。这些 OI 没用,所以不推荐。

调试工具

问:有什么工具帮我查运行错误/下标越界/数值溢出?

答:按需求添加编译选项 -g3 -fsanitize=address,undefined -D_GLIBCXX_DEBUG 等并使用对应的 gdb asan 等工具。

注意这些会让程序变慢,测速不要加,而且不能和 -O2 一起加。

  • -g3对应 gdb 不赘述了,基础调试工具。不过,有时候直接输出调试更好;标准错误输出 stderr(比如 cerr<<x<<endl;)可以立即输出,多输出几个断点也能找到 RE 在哪。
  • -fsanitize=address,undefined 添加后可以检查一些数组越界和无符号溢出(取模题很有用)等,参见:Awesome sanitizers
  • -D_GLIBCXX_DEBUG 可以让一些库函数和 STL 多检测(例如开了之后 lower_bound 会先检查是不是排好序了)。这个检测可能会提高程序的时间复杂度,测大数据不要开。

忘改调试/注释

问:调试的时候注释了 freopen 忘记恢复/忘删调试语句爆零?

答:采用宏 #ifdef MYDEBUG,不要注释。

采用 #ifdef MYDEBUG #endif 包裹调试语句,采用 #ifndef MYDEBUG #endif 包裹调试要屏蔽的语句(比如 freopen)。调试时,给编译选项加上 -DMYDEBUG 即可。

另外:Windows/Linux 命令行都可以用 2> 把错误输出定向到文件。例如 Linux 下 ./aa < aa.in > aa.out 2> log.txt 可以从 aa.in 读数据,向 aa.out 写数据,把 cerr 都输出到 log.txt。特别地,2> NUL 忽略错误输出,> NUL 忽略输出。(程序本身没 freopen 对应的 stdin stdout stderr 才有用)Windows 也可以,除了 ./aa 改成 aa.exe

输入输出优化

问:用什么输入输出?要读入优化吗?

答:平时用关同步 cin/cout,量巨大时用 cin.read() cin.gcount()/cout.write() cout.flush()

注意:

  • 关同步。在 freopen 后面加上 ios::sync_with_stdio(false); cin.tie(nullptr);
  • '\n' 代替 endl 以免刷新输出缓冲区开销。
  • 需要记一下设置输出小数格式的语句 cout << fixed << setprecision(10) << endl; 从此开始保留固定 $10$ 位小数;cout << defaultfloat << setw(9) << a << endl; 从此开始保留 $9$ 位有效数字。(这里省略了 std::
  • 奇奇怪怪的输出格式要求建议手写函数转成字符串输出。
  • 量巨大:一般 cin/cout 调用总次数(比如输入输出数字个数)超过 $2\times 10^6$ 次算巨大。输入输出单个长字符串开销不大。

建议不用 scanf/printf,现在效率一般不如关同步 cin/cout,且格式化字符串和取地址容易出错。调试也用 cerr 即可(嫌格式麻烦可以把调试输出语句单独抽出来写成函数)。

对于很大的输入输出,手写函数解析输入输出字符串,然后使用 cin.read() cin.gcount() 一次性输入大量内容,使用 cout.write() cout.flush() 一次性输出大量内容。(和 fread/fwrite 功能相同,但更可读)一般建议开一个 $2^{16}$ 字节的 char 数组做输入输出缓冲区(也就是一次性最多读写这么多内容),开小了会慢,开太大太占内存而且卡缓存。

注意手写之后就不能和普通 cin/cout 混用了。cerr 因为是独立的错误输出所以不受影响。

示例代码:

// 感谢UT和前人提供的基础代码。示例代码为了简短只有 int
#include <bits/stdc++.h>
using namespace std;
const int S = 1 << 16;
char buf[S], *p1, *p2, obuf[S], *O = obuf;
int getChar() {
  if (p1 == p2) {
    p2 = (p1 = buf) + cin.read(buf, S).gcount();
    if (p1 == p2) return EOF;
  }
  return *p1++;
}
int readInt() {
  bool f = false;
  char ch;
  while (!isdigit(ch = getChar())) f |= ch == '-';
  int x = ch & 0xf;
  while (isdigit(ch = getChar())) x = x * 10 + ch - '0';
  return f ? -x : x;
}
void putChar(char c) {
  if (O == obuf + S) cout.write(O = obuf, S);
  *O++ = c;
}
void printLine(int x, char c = '\n') {
  if (x < 0) putChar('-'), x = -x;
  if (!x)
    putChar('0');
  else {
    static char stk[21];
    int t = 0;
    while (x) stk[t++] = x % 10 | '0', x /= 10;
    while (t) putChar(stk[--t]);
  }
  putChar(c);
}
int main() {
  cin.tie(nullptr)->sync_with_stdio(false);  // cin 另一种关同步写法
  printLine(readInt());
  return cout.write(obuf, O - obuf).flush(), 0;
}

开栈空间

问:我本地测试怎么开大栈空间?

答:Linux(含 NOILinux)在终端运行程序前先运行指令 ulimit -s 1000000,Windows 编译选项添加 -Wl,--stack=1000000000

Linux 下 ulimit 可以调整终端包括它调用的程序的诸多限制,-s 1000000 表示把栈空间设为 $10^6KiB$(略低于 $1GiB$)。Windows 栈空间可以在编译时添加 -Wl,--stack=1000000000 设置为上限 $10^9$ 字节(略低于 $1GiB$)。当然栈空间就算取消限制还是算在总内存限制的。

不要设置为 unlimited,防止由于无限递归导致系统崩溃。

默认情况下,Windows 栈空间通常是 $2MiB$,Linux 通常是 $8MiB$。这样如果 dfs 太多层会超过栈空间上限运行时错误崩溃。好消息是 NOI 系列正式比赛都会开无限制栈空间,不超总内存限制就行。

测时间和内存

问:如何测自己程序时间和内存?

答:Linux 用 time ./程序名 测时间,ulimit -v <内存限制KB数> 测超内存限制。Windows 用程序内 clock() 测时间,用命令行 cmdsize 测内存。

Linux 编译好程序 aa 后用 time ./aa 测时间(要定向输入输出就 time ./aa < aa.in > aa.out),看的是几个值中的用户时间(user);用 ulimit -v 524288 限制内存到 $512MiB$,建议实际开 ulimit -v 500000 即可,留点空余。这个测试方法和 NOI 规则相同(看的是申请空间而不是实际使用的页数)。

想改变 ulimit -v 内存限制请关掉终端重开。 同一个终端 ulimit 开内存只能从大往小开,不能反着来。

Windows 在程序里添加 cerr << clock() << endl; 来输出运行时间(建议也和其他调试一样用 #ifdef MYDEBUG #endif 包裹)。用命令行 cmdsize aa.exe 命令测内存。

此处没有推荐难记的做法比如 std::chrono,会的可以用。

注意手动输入数据也算时间,测时间请开 freopen 或者用 < aa.in > aa.out 定向输入输出文件。

考试环境是 Windows

问:考试环境是 Windows 怎么办?还有前面没提到的吗?

答:务必打开显示文件扩展名。

你可以本文内搜索 Windows 这个词。

  • 如果你使用 Windows 系统,请务必把文件查看中的“显示文件扩展名”打开,不然你命名为 a.cpp 实际上是 a.cpp.cpp 直接爆零。

不要写超标语法

问:用超标/被禁语法爆零了怎么办?

答:平时就别写超过 -std=c++14#pragma 之类的违禁品。

至于有啥?自己开编译器 -std=c++14 测!NOILinux 默认这个不用开。

样例

  • 小明参加 NOIP。
  • 小明详细读完了四个题并手算了每个题最小样例,期间看完第一题直接顺利想出了做法,这些一共花了 15 分钟。题目的输入输出文件名是 aa problemb cti di。(现在是 15 分钟)
  • 小明想了想第二题,10 分钟想出了 60 分做法,满分暂时不会。他又去想第三题,10 分钟想出了第三题做法是 DP,但是不好写,好写的暴力是 30 分其它部分分也不好写,于是又花 10 分钟想清楚写下几个主要函数的外壳和关键的状态数组在原问题的准确意义。剩下第四题看了 5 分钟啥也不会,只能写 20 分暴力,如果用数据结构维护可以到 45 分,但问题本身就复杂要写很久。(现在是 50 分钟,小明会上限 305 分,其中 210 分好写)
  • 小明 20 分钟写完第一题并通过所有大小样例,手造的 1 0 边界数据通过,极限数据开查错编译/调试选项测试报了个越界,发现一个数组下标开错了,花 10 分钟。(现在是 1 小时 20 分钟,写了 100 分)
  • 小明 30 分钟写完第二题 60 分并通过小样例,特殊性质大样例没过,查错编译/调试选项报了个 int 溢出,发现是有个地方取模漏了。10 分钟解决通过特殊大样例。(现在是 2 小时,写了 160 分)
  • 小明再想想第二题满分怎么做,但几分钟无果,上了个卫生间放松还是没思路,决定继续写后面的。(现在是 2 小时 10 分钟)
  • 小明觉得第三题难写,决定先写第四题暴力。15 分钟写了 20 分通过小样例。(现在是 2 小时 25 分钟,写了 180 分)
  • 小明利用代码框架在 45 分钟内写出了第三题,但过不了小样例。开查错编译/调试选项测试没错。先测了手造的 1 1 边界数据过不了,花了 5 分钟修好,但还是过不了小样例。考虑到其他题都写过了,小明决定开始对拍调试。(现在是 3 小时 15 分)
  • 小明 10 分钟写完了小暴力和数据生成器并测试暴力过了小样例。(现在是 3 小时 25 分)
  • 小明开始从小到大对拍数据,在 n=4 拍出错了,他把权值手动改小找到了更简单的错误数据。然后小明在代码中间用 #ifdef MYDEBUG cerr #endif 加了调试输出中间结果,并用 #ifndef MYDEBUG #endif 框住了 freopen,重新开查错编译/调试选项编译时添加了 -DMYDEBUG,方便调试时读其他文件 ./cti < cti.in > test.out 2> cerr.log。他运行小数据并手算中间状态的数学意义该有的值,找到了几个错误。反复几次后他暴力能跑的范围小数据对拍上了,并且极限数据也没报错。这些调试用了 30 分钟。(现在是 3 小时 55 分,写了 280 分)
  • 现在小明时间不多了,决定再去卫生间冷静一下。突然他想到利用反悔贪心的思路能解决第二题,并且应该好写。他尝试脑内调整法大概验证了下正确性证明思路。(现在是 4 小时)
  • 小明把原来的第二题代码备份了一下,然后开始写第二题满分做法。但这时候电脑卡死了,小明举手示意监考,监考无法解决只能重启,给小明加时 5 分钟。(现在是 4 小时 5 分)
  • 幸运的是,因为贪心代码很简单,他 20 分钟就写完并且过了大小样例,开查错编译/调试选项也没报错。(现在是 4 小时 25 分,写了 320 分)
  • 小明最后 5 分钟检查程序,先关闭代码文件,检查了文件夹路径和文件名,然后复制题面PDF第一页的编译选项,没加自己的选项编译通过了四个题,并且运行了小样例,肉眼和 diff 分别验证了小样例正确性。然后关闭了所有命令行和窗口,考试结束了。
  • 加时的 5 分钟小明又检查了一次文件夹,文件名和编译通过。
  • 成绩出来了,小明第二题和第三题还是挂了 3 个特殊边界数据点,最后总分 $305$。
  • 小明感叹一声:还好不是 CSP-S,不然只有 4 个小时时间,自己恐怕没时间做第二题了。

防爆零指南之:其他内容推荐和琐碎细节合集

看太多会记不过来,而且其中重要内容在前面都有了。没时间不用看。

如果你想看:

部分我查过的其它资料列表(不要通读它们,本文足够)

我的个人链接(厚颜无耻)

从理解斜二倍增,到放弃斜二倍增

2025-10-30 04:26:21 By liu_cheng_ao

对于梦熊联盟,以及其实际控制人和主要管理人员实际控制的其它机构,禁止任何人于正在临时或长期参与其任何活动期间,以任何直接或间接方式转载,引用,使用,传播或展示:本人在2024年5月或以后创作的任何内容或片段,包括所有声明为公开发表的内容在内!学生或教师本人自行阅读学习为被允许的例外情况,但此授权不包括在上述实体活动期间在其平台上进行转载,引用,传播等。

公开资源推荐和征集:

什么是斜二倍增?我看不懂斜二倍增怎么办?

问题: 我有一棵有根树,想支持在线动态 $O(1)$ 加叶子,在线 $O(\log n)$ 查询路径可合并信息(比如路径最大值个数,路径最大子段和),内存 $O(n)$,怎么办?

在下文中,为了简便,我们设定:查询的信息基于点权而非边权。

传统解法:

  1. 直接上LCT:但是难写且常数大。
  2. 树剖:因为动态加点得随机选重儿子,但是如果数据不随机又得上平衡调整,然后你发现自己发明了LCT。
  3. 每 $\log n$ 层树分块/取关键点:这思路能做,但还是没那么好写。
  4. 树上倍增:好写好用,但是每个点要 $O(\log n)$ 预处理,怎么办?

我们考虑怎么优化树上倍增。树上倍增预处理的信息总共 $O(n\log n)$ 个,这很有用,但是做路径查询其实不需要这么多。你看线段树,树剖+线段树都是 $O(n)$ 空间就能做路径查询了。能不能对倍增也这么干?

尝试直接让线段树上树。方便起见,我们取完美线段树(区间长度都恰好是 $2$ 的幂):我们对于树上每个到根路径,把它当成一个深度为下标的序列,预处理出线段树上所有应该有的点。

也就是说,对于每个树上的点 $u$,设它的深度为 $d(u)$,那么:线段树上每有一个以 $d(u)$ 为右端点的长度 $L$ 的区间,我们就预处理从 $u$ 向上 $L$ 个点的路径段信息。(深度从 $1$ 开始算)

线段树.png

可以发现,这等于:对于每个点 $u$,我们处理了向上长度 $2^1,2^2,\dots ,2^{\mathrm{lowbit}(d(u))}$ 的所有区间。也就是我们对树上倍增添加一个上限 $2^{\mathrm{lowbit}(d(u))}$。我们可以像线段树那样,查询每个点到根路径的任意区间,那么仍然可以 $O(\log n)$ 查找LCA以及求路径可合并信息。

这样,我们已经把树上倍增几乎变成线段树的 $O(n)$ 复杂度。

但还有一个小问题:线段树虽然总复杂度是 $O(n)$ 的,但是单个位置为右端点的区间数仍然可以达到 $O(\log n)$。那么树上这种深度的节点很多时复杂度还是会退化到 $O(n\log n)$。如果能把线段树每个区间右端点变成互不相等的,就能解决这个问题。

斜二倍增

这其实很简单:我们把每个线段树区间的定义从两个子树区间的并,改成:两个子树区间的并后面再多加一个点。也就是形如:

斜二线段树.png

这个线段树称为斜二进制线段树。这样每个点存的区间数都变成了严格的 $1$ 个,而且仍然可以线段树查询(只是每一层要多合并一个单点)。具体来说:设 $L(x)$ 表示以 $x$ 为右端点的斜二进制线段树区间长度(上图橙色数字),则对于每个树上的点 $u$,设它的深度为 $d(u)$,我们预处理从 $u$ 开始向上长度为 $L(d(u))$ 的路径段信息即可。$L$ 数组倍增预处理即可。

之后的用法就和普通倍增一样,具体代码可以参考介绍博客 - UT

我不想学斜二倍增!普通倍增能代替吗?

其实可以,直接按前文所述对倍增添加一个上限 $2^{\mathrm{lowbit}(d)}$即可。此处 $d$ 是倍增起点的深度或下标。

那么怎么解决同深度点太多时复杂度不对的问题呢?

方法一. 如果问题可以换根,可以先遍历树找一个好的根,总存在一个根使得每个点深度的 $\mathrm{lowbit}$ 位数和是 $O(n)$ 的。

证明和构造思路:考虑对树进行黑白染色,取黑/白根时所有同色(或者异色,看深度定义)点的深度全为奇数。所以递归到较小颜色为偶数的情况里选取,然后继续递归即可。

方法二. 这个更简单,而且通用:我们一开始均匀随机选取一个全局的 $[1,2^{\lceil \log n \rceil}]$ 正整数常数 $C$,然后我们定义 $\mathrm{lowbit'}(x)=\mathrm{lowbit}(x+C)$,改用 $\mathrm{lowbit'}$ 做倍增上限即可。

证明思路:这相当于把所有下标和线段树区间整体平移了一下,容易发现不影响线段树的复杂度。但这会让每个点 $\pmod{2^{\lceil \log n \rceil}}$ 都变成均匀随机的,而均匀随机整数的 $\mathrm{lowbit}$ 期望(平均)等于 $1$。所以期望复杂度正确。

缺点:倍增数组不定长,内存分配可能是个问题。不过出题人不刻意卡的话 vector 即可。卡就手动分一下。

因为本来就差不多(随机化和确定性的区别)目前可以完全代替斜二倍增,适合不想学新代码的选手。

题外话:对于有些问题倍增 $O(n\log n)$ 个信息是必要的。比如树上求两个路径的最长公共前缀二分哈希时,必须要任意两个点都能走相同长度。

我普通倍增也不想学了

树分块:每 $\log n$ 层树分块/取关键点,关键点个数是 $O(n/\log n)$ 然后关键点之间跑带 $\log$ 的算法,查询的时候暴力跑到第一个关键点即可。

代码

随机偏移倍增(方法二)求 LCA 的核心代码(我写的比较繁杂,可以根据你自己的倍增代码修改):

和普通倍增唯一区别是倍增步数取了个 $\min$。

int L(int x){return __builtin_ctz(x+C);} // lowbit位数。其中C是全局预处理常数,在O(n)值域随机的一个正整数
int B(int x){return 31-__builtin_clz(x);} // 二进制最高位数
// dep:深度 f[i][j]:i的2^j级祖先,其中j<=min(B(dep[i]),L(dep[i]))
int lca(int u, int v){
    if(dep[u]<dep[v])swap(u,v);
    int dd=dep[u]-dep[v];
    while(dd){ // 跳到dep[u]==dep[v]
        int di=min(L(dep[u]),B(dd));
        u=fa[u][di], dd-=(1<<di);
    }
    for(int i=B(dep[u]);i>=0;){
        int di=min(min(B(dep[u]),L(dep[u])),i);
        if(fa[u][di]==fa[v][di])
            i=min(i,di-1); // 不用再尝试>=di的了
        else
            u=fa[u][di], v=fa[v][di];
    }
    if(u!=v)u=fa[u][0],v=fa[v][0];
    return u;
}

坚决反对与虎谋皮,以营销炒作的方式“推广知识”,破坏社区秩序的行为!

坚决反对通过向部分不懂算法的家长/教练危言耸听,吹嘘特定知识重要性,强迫学生学习,破坏教学秩序的行为!

坚决支持建设高质量公开资料推荐平台和日报刊物平台!

对于梦熊联盟,以及其实际控制人和主要管理人员实际控制的其它机构,禁止任何人于正在临时或长期参与其任何活动期间,以任何直接或间接方式转载,引用,使用,传播或展示:本人在2024年5月或以后创作的任何内容或片段,包括所有声明为公开发表的内容在内!学生或教师本人自行阅读学习为被允许的例外情况,但此授权不包括在上述实体活动期间在其平台上进行转载,引用,传播等。

OI 中的小资源合集[utilities]

2025-10-27 21:50:01 By liu_cheng_ao

《算法问题教学笔记》计划(基于竞赛,可自学的算法设计教材纲要探讨)

2025-10-21 04:32:19 By liu_cheng_ao

个人著作权声明:严禁任何未经本人(刘承奥,常用笔名/网名:蔡德仁 CommonAnts LCA liu_cheng_ao)书面授权者在梦熊联盟,或者任何虚假宣传或不实营销炒作或不正当竞争行为严重的 OI 机构的课程内或交流平台(包括但不限于品牌集训线下讨论,交流群,OJ,公众号,视频号等)上引用、传播、讨论此内容,以及本人于2024年5月及之后发布的所有内容,包括声明为公开的内容在内。

鉴于算法设计进阶的教材的缺失,以及算法竞赛即将随着全社会教育资源的进步,完成它作为算法乃至计算机科学自学的社会组织绝对核心的历史使命的现实:我准备写作一部整合整个算法竞赛体系的,自洽的教材。

这本教材应该是对至今为止的整个算法竞赛的总结,是算法竞赛转型之前必须做的整理。

我设想中这部教材应该具有以下特点:

  • 它应该包含算法竞赛的大部分成果,除了那些基于数学或计算机科学界的需要非中学知识才能理解的理论作为核心方法或者前置条件的。(人话:科技题除外,除非是竞赛特有的科技)
  • 它应该可以自学。然而,由于上一点,它的内容不可避免地难。因此我们假设读者在阅读之前就已经有了基本的算法设计和实现能力,相当于学完了NOIP算法并且有NOIP250分的水平。更精确地,我们假设的读者就是在弱校自己刷题刷到 NOIP250 分的学生。
  • 它应该可以自学。即使我们已经假设读者的基础水平,也必须自洽地讲完所有概念。尤其是研究方法,算法设计的范式、技术和技巧,数学的工具和动机等必须从零开始。我们应该认为读者虽然有基础水平但他们基本上通过死记硬背获得知识,因此我们仍然必须推导它们以展示数学动机和方法。
  • 它应该可以自学。所以它应该包括少许学习方法的讲解,例如做笔记等。
  • 它虽然应该可以自学,但我们不可能在这些体量里塞入足够细节的讲解。因此可以自学是指结构安排适合自学,而不是代替读者的同学老师和AI包办细节。
  • 它应该包括竞赛主要学的各种知识,而不仅是算法。至少应该包括四个方面:算法处理的离散数学对象(序列,树,图和字符串等),常用的其它数学理论(概率统计,博弈论,数论,代数等的基础算法问题),具体的算法(递推状态,数据结构,优化和构造等),计算理论(信息,计算模型,问题类和归约等)它不能像一般的大学算法教材那样只涉及其中一两个方面的知识,否则作为可自学教材将是极不完整的
  • 离散数学组合对象,以及算法,应该构成独立的核心内容。换句话说,如无必要,在这两部分不使用需要其他数学基础的例子。
  • 关于代码实现,我建议这本书只给出一些诸如标出变量的具体数学意义,结构化程序设计等对于包括伪代码的一切冯诺依曼式编程语言适用的实现内容。至于现代计算机编程和架构不在考虑范围内,它们应该单独看书。
  • 因为这本书要包括几方面知识,这些章节必然不构成对于知识的分类。也就是说,将会频繁发生类似知识在不同章节以不同视角被反复提及的过程。我们不反对,而且鼓励这样的联系,作为自学教材。很多经典例子同时属于不同分类,我们将其归于其最常用的那一类,如果没有则归于推出其的最主要动机(难点)那一类,并在其余出现位置反复引用。这种反复引用是减少体量的重要手段。不过每个小方法至少应包括独有的一个引入例子和一个核心例子。
  • 它不必包罗万象,不收录不常见的可自己推出的技巧。但应该在更常见的技巧和例子中蕴含了推导的动机和理论。
  • 它应该对接学术界。这不是说要细查引用,而是说应当给看完这本书的集训队学生指出一些具体的人,事,地。
  • 在这本书写完的时候 AI 应当已经达到了相当的水平,但仍然不能可靠地针对人教学。AI 在这时最大的作用仍然是智能搜索和整理全部的对应知识,这不仅包括理论也包括方法,数学工具,思路,以及对具体题例给出带思维链的解法。因此多用 AI 对自学的元认知,描述自己的方法并学习做笔记是有好处的。使用 AI 辅助对编程能力学习也有帮助,此处不详述。
  • 它的每个章节应该含有习题,大部分是 OJ 题,一部分(每节至少一个)笔答思考题作为章节数学概念/方法的应用例子(通常是基于某个 trick 或者某个算法题的)。原则上在覆盖所有较常见技巧的前提下题目应该尽量简省。我希望能将全书题数控制在 1500 道以内(如果可能的话控制在 1000 道以内),包括所有例题和所有习题。
  • 相比一般的教材按算法/问题专题分类,它是倒过来用研究工具、对象、方法、动机来统领具体算法和问题的结构。因此使用这本书的读者必须同时不断了解具体问题和算法。(比如刷题)本书基本上是给不缺题例但缺乏学习方法和研究视角的学生准备的,不适合不做题的人使用,否则多少有过度抽象之虞。
  • 不应该只因为一个技巧简单或特例就取消它的名字,反而应该多取名字。取名字意味着被意识到。(例如刷表,填表,悬线法等。)但当难度明显低于读者水平时,为了整体理解取消特例的名字。
  • 同时满足非缩写,非专名,仅专业内使用的英文概念应翻尽翻。(border → 边缀,hash → 散列)
  • 如果还未被广泛接受的概念名词有更好的称呼(和内容更相关且不明显变长且不损失专有性),改用更好的称呼。(例如 珂朵莉树 → 颜色段均摊)(但是 猫树 → 二区间合并 或 记忆化分治 之类的是否应该?太长了。)
  • 作为正文中的理论、结论、定理等不应该立刻写出详细证明,而应该用写出前的推导动机和写出后的证明思路简短说明。不要用证明细节打断阅读思路。证明细节可以后续单独收录查阅。
  • 同一个小节内的例题难度递进不应该太大。具体来说,差距最好小于,最坏也不能超过洛谷颜色的 2 级或者 CF 分数的 1200 分。不能像算法导论一样 DP 第二个例题放矩阵链乘法!习题可以大一些,但难的应该标出。
  • 体量问题:预估为之前算法竞赛教材单本书(比如刘汝佳黑书蓝书紫书)的 3 倍。算法一个部分占一本书。组合对象和离散数学,其他数学,计算理论,附录四个部分每两个占一本书。

(填写中…)内容大纲(大致是目录)

“方法”可能指[technique, trick, view, method, paradigm, schema, prototype, model]等内容,待细化。

“工具”≈刻画和研究问题的“套路”。

带问号的表示自己或者下属内容还没想好怎么放以及具体内容,先塞着。

括号是注释。

## (C++ 宏连接符)表示这个小节其实不是真的另起一页的小节,和兄弟是连成一大篇的。目录里缩进只是表达内容结构。

部分过度展开的内容先放着,纲目完成后统一简省。

内容大纲

  • 第零章:引入(有让读者确认自己水平合不合适看这本书的作用)

组合对象和离散数学

每一个章节同时是该组合对象上的:1. 一类算法问题 2. 用同一工具解决(组合性质/刻画方式/算法prototype)

  • 序列
    • 序列基础
      • 前缀和与差分,颜色段
      • 画图-打表和平面嵌入(画到平面上!)
      • 扫描和换维
      • 压缩标号和信息量
      • 二分,分治和倍增
    • 二维嵌入
      • 区间
        • 区间集合的结构(如何画到平面上)
          • ##区间和平面点集形状的对应
          • ##嵌套集和子树
          • ##不交集,环区间和无根子树
          • ##单调区间
          • ##定长区间
        • 区间统计问题
          • 扫描维护(枚举端点)
          • 分治和倍增
          • 分块和按大小分类
          • 间隔采样法(主要是像处理定长k区间每隔k个找一个位置,或者区间超过一半必过中点这类技巧。)??
          • 区间统计经典问题??(利用区间性质+问题本身性质的。如区间颜色数,mex,“众数杀手”等。是否拆分?)
      • 二维偏序问题
        • 二维偏序极值问题(单调栈、单调队列、双端插入、线段树)
        • 二维偏序链问题(上升子序列)
        • 二维偏序链-反链互补(Dilworth 定理;二维偏序是链和反链互补的充要条件,调整法等应用)
        • 二维偏序结构和杨表
      • 二维凸性问题??(移入优化-构造或者计算几何?)
    • 多维嵌入
      • 高维前缀和??
      • (待填)
    • 排序和查找
      • 排序算法
        • 比较排序(快排、归并、堆、比较排序下界)
        • 值域排序(计数、基数、桶)
      • 排序分析
        • 01 原理(要单开一节吗?)
        • 排序电路问题(排序网络、区间排序电路、一些 I Can't Believe It Can Sort 的正确性等)
        • 更多排序分析问题(逆序对分析折线法,以及不能 01 分析的问题等)
      • 二分查找??(二分查找应该划在序列?其余的二分算法思路划入子问题-分治-倍增-递归)
        • 二分查找基础(包括双序列二分、三分、估值查找、跳跃查找等思路)
        • 减治二分查找(按比例降低问题总规模的线性复杂度递归方法)(主要技巧 1. 间隔采样后递归+微调 2.同时维护多个分点,每次消除至少一个分点占常数比例的一侧)
          • ##快速选择问题(第 $k$ 小和中位数,median of medians)
          • ##多序列二分问题(含分散层叠[fractional cascading])
          • ##经典问题(如 UOJ 891)
          • SMAWK??(放dp里?)
    • 括号序列和 $01$ 序列
      • 嵌套匹配问题(以及局部消除类问题)
        • 括号树
      • 单调匹配问题(两个 $01$ 序列中 $0$ 和 $1$ 之间依次按顺序匹配和相关问题)
      • 前缀和??和折线法(画到平面上)
    • 排列??(作为单一置换?作为序列的排列似乎不必单独开。内容均在递推计数和组合计数中。作为置换群的排列内容在代数中。)
      • 环??
    • 最值问题
      • RMQ
      • 笛卡尔树
        • (待填)
        • 笛卡尔树扩展(每个点同时向左、右第一个比自己大的位置连。此左/右树的并同构于笛卡尔树的平面对偶图)
    • 连续段问题
      • 算术统计(视为 $\arg\min((r-l)-(max-min))$;视为每对相邻位置蕴含关系的闭合子图;视为 $[l,r]\mapsto [\min,\max]$ 的不动点)
      • 连续段集合结构
      • 析合树和PQ树
  • 集合
    • 集合基础
    • 逻辑表达式和位算术(布尔算术)
    • 背包问题??
    • 格点问题
      • 子集和值域问题
    • 数位-字典序问题??(应该和位运算分治、Trie 树之类的放一起??属于序列吗??)
      • (待填)
  • 树??
    • 树基础
      • (待填)
      • 树的重心
      • 树的直径和中心
    • 子树(递归/嵌套??)结构??
      • 有根子树和无根子树(以及和区间的关系)
      • 树上遍历序
        • ##DFS序
        • ##欧拉序
      • 最近公共祖先问题
    • 树上统计
      • 子树递归统计??
        • 子树递归和合并(作为子问题)
        • 启发式合并
        • 树链剖分(以及和启发式合并的关系)
        • 树上复杂度分析问题
      • 树分治
        • ##点分治
        • ##边分治
        • ##链分治
        • 分治树
      • 连通块问题
        • 枚举 LCA(→ 启发式合并)
        • 容斥
      • 路径问题
      • 邻域问题
      • 树上位置关系问题(虚树)
        • 虚树
    • 二叉树
      • 二叉树遍历序
      • 三度化??(孩子-兄弟表示??)
    • 序列和树
      • prufer序列
      • 序列问题在树上的延拓??
        • 最值问题(kruskal重构树)
        • 连续段问题
  • 图论??
    • 图论基础(待填)(图的特殊研究方法之一是由局部性质可扩展至整体性质,即讨论某个特殊图等于讨论了含有同构/同胚子图的所有图)
    • 生成树问题(以及用树边-非树边研究图的问题)
      • 最小生成树问题
      • 生成树(搜索树)刻画图
        • ##DFS树
        • ##BFS树
        • ##其它搜索树例题
    • 路径问题(待填)
      • 单源最短路
        • 最短路树
      • 全源最短路
    • 割(划分)问题
      • (待填)
      • 无向图最小割
        • 全局最小割
        • 最小割树
    • 圈(欧拉子图)问题
      • 欧拉路径和欧拉回路??
    • 连通度问题
      • ##边双连通
      • ##有向图强连通
      • 点双连通
        • 仙人掌??(是否移入特殊图??)
        • “圆方树”??
      • 连通度问题
    • 匹配-覆盖-染色类问题
      • 点独立集、覆盖、染色
      • 匹配(边独立集)和边染色
        • 匹配的结构
        • 二分图最大匹配
        • 二分图最大权匹配(KM)
        • 一般图最大匹配(带花树)
        • 一般图最大权匹配
        • 边染色问题
    • 有向图可达性和偏序问题
      • 有向无环图
      • 传递闭包和传递图
      • 竞赛图(单有向完全图)
    • 代数图论基础??????
      • 图和线性空间????
        • 边空间,割空间,圈空间
        • 邻接矩阵和关联矩阵
        • 矩阵树定理
        • LGV
        • tutte矩阵(备忘,待删除)
      • 图散列
    • 二分图(从这里开始是特殊图。像线图这样纯概念的怎么放?)
      • 网格图
    • 平面图
      • 对偶图
    • 树和序列结构的特殊图
      • k-tree
        • 外平面图
        • 串并联图(广义)
      • 树分解
        • ##弦图
        • ##区间图
        • ##环区间图
        • 树分解(是否保留?)
  • 字符串
    • 字符串基础
      • 子串统计问题
    • 自动机问题
    • 子串相等约束问题
      • 周期和边缀[border]
      • 回文
    • “其它(组合结构)”??????(Lyndon, Runs, 之类的)
  • 组合推导(组合对象的方法总结篇)
    • 组合推导基础(封闭性,等价类,偏序等最基本性质。以及最基本的整体刻画理论,实验等研究思路。)
    • 实验法(相对而言,理论法是用一个数学理论工具整体刻画研究对象。但是似乎不应该成为章节。)
      • (枚举所有小情况,观察渐进增长等例子)
      • 画图-打表(几何直观,刻画,表示的例子)
      • 特例性质的推广(延拓)例子
    • 组合模式和“Ad-Hoc”??
      • (例子)zig-zag构造
    • 组合统计算法
      • 扫描维护(按顺序枚举最小元素)
      • 分治和倍增
      • 分块和按大小分类
      • 间隔采样法
    • 组合推导技术(挖掘组合性质)
      • 嵌入,换维
      • 调整法(优化、构造)(局部增删,邻项交换,局部合并)
      • 增量、差分(指解之间求差/比较,比如所有解减去基准解的技巧)
      • 整体刻画和表示(画图打表,以及表示法)
      • 不变量、特征量、势能
      • 信息量、压缩
      • 局部法(把全局判定拆分为每个局部的判定,例如 CSP-S2025T4 的推导,或者 Cook-Levin 定理等。大多数情况下局部是指扫一遍或者算法跑一遍验证时的时间轴的局部,只考虑当前+前 O(1) 个时刻)

算法

按照算法范式/动机分类。每支开篇是自己解决的代表性的问题形式。章节引入问题必须可以从简单到难反复深入并反映大部分思想。

  • 枚举-状态-递推
    • 引入:组合统计问题(方案,合法方案,最优化/计数/判定/构造)
    • 枚举-搜索
      • (待填)
      • 判定性计数(指统计所有合法方案,合法性定义为存在更细节的解)
        • 算术优化(重写判定条件)
        • 代表元-最小表示-补集容斥
        • 反演容斥(拆贡献)
    • 动态规划(OI,含计数递推等非最优化问题)
      • 动态规划基础
        • ##状态(基本定义,按是否已经考虑引出分界线划分后合并对另一侧相同影响的)
        • ##状态的信息视角(状态机压缩,及其局限性)
        • 状态转移方程和状态转移图(特别是涉及多个状态的转移以及增量(刷表法)/减量(填表法))
        • 子问题(子问题视角以及分治递归/倍增视角的基本介绍。主体部分在子问题-分治-倍增-递归。)
        • 方案集合(整体视角,合法方案集合的结构)
      • 状态和转移的简化
        • 基础和算术简化(拆多路转移,拆独立性,前缀和等基础操作)
        • 时序简化(包括反转扫描顺序,跨步转移作为状态机的局限性,dijkstra,各种微调时序等)
        • 状态转移图简化(找图局部重复,以及优化建图)
        • 最优性简化(考虑将DP下标的信息尽量移入值,DP值改为维护所有极优解的集合。只保留极优解实现简化。此法涵盖最优性去状态、换维、去维等。)
        • 计数简化(特别是将贡献拆入多步转移和状态)
      • 整体维护
        • 整体维护基础(扫描整体维护逐行变化的思想,基本的分段维护)
        • 二维嵌入(含二维凸集和二维偏序链对应的slope trick,单调栈等)
        • 多项式和插值
      • 最值(最优化)递推
        • 最值的算术优化?(例如 $\max(\lvert a-b\rvert) = \max(\max(a-b,b-a))$ 等内容。应该移入优化-构造。)
        • 决策单调性
        • 凸完全单调性和双线性(四边形不等式和斜率优化)(蒙日矩阵应划入代数?或离散数学?或省并?)
        • 凸性优化(二分斜率-wqs二分,扫描斜率-维护最优决策,整体维护等)
      • 计数递推(判定性计数递推)
      • 有后效性的递推?(应划入优化-构造或迭代-增量?)
        • 迭代/松弛方法?
        • 差分约束类问题?(有后效性的最优化递推求解)
        • 解概率期望DP的线性方程组?(有后效性的计数递推求解)
      • 动态规划模型(具体的各种模型还是不要散在各个组合对象内??)
        • 序列×DP(序列和高维序列,区间,环形,括号序列,数位/字典序,排列计数)
        • 集合×DP(背包,子集,位运算,状压,插头/轮廓线)
        • 树×DP(子树,复杂度分析)
        • 其它 DP 经典问题
  • 子问题-分治-倍增-递归
    • 引入:分形序列查询问题
    • 子问题??
    • 分治-倍增-递归??
      • 增量(减治)
      • 分段(分常数块)
      • 采样(分常数大小的块)
        • 奇偶归并
        • 倍增采样法
        • cascading
        • scaling
      • 微调技术??
      • 附加结构
      • 复杂度分析
  • 数据结构(维护-修改-查询)
    • 引入:区间可合并信息查询问题(区间半群)
    • (待填)
    • 均摊严格化
      • 分步-离散化方法
      • 分段整体处理
      • 随机化方法
      • 例子
        • ## std::vector和队列重构
        • ##二进制分组的严格化及随机化
        • ##斜二进制倍增及随机化二进制倍增
  • 优化-构造
    • 调整法和最优性/存在性证明(优化-构造共通的整体组合研究方法)
      • 调整技巧
        • 局部交换
          • 调单项到开头/结尾/树根/叶子等(直接贪心法,直接选第一项/最后一项)
          • 将单项向某个方向调整(例如重心方向之类的)
          • 邻项交换
          • 分界线两侧交换错位重拼
        • 局部合并(缩并,归纳)
        • 微元法(以及其它扩大可行域的方法)
        • 反悔法(可逆操作,保证任何时候接下来的调整操作还能得到所有可行解)
        • 二维偏序互补性
        • 其它
      • 凸性
        • 凸集和凸函数
        • 定义归纳法(例如方案集合可以递归由保凸性运算构造出来)
        • 经典模型法(使用凸多边形、模拟费用流、蒙日矩阵、拟阵等直接刻画问题)
        • 局部法(直接证二阶差分单号或者 $i-1,i+1$ 调整出两个 $i$ 平均化)
        • 斜率法(枚举斜率证明每个点都在边界上,也就是说带斜率权值的最优解是连续变化的)
        • 凸性的直观(合法解可平均化)(因此凸性总是有介值定理等描述平均变化过程的关系)
        • 凸共轭(芬切尔-勒让德)
    • 优化算法
      • 贪心算法
        • 模型法(用下述内容建模。见模拟费用流、拟阵等)
      • 线性规划和网络流
        • (待填各类基础网络流)
        • 线性规划
        • 差分约束
        • 模拟费用流
      • 凸优化
        • (待填)
        • 蒙日矩阵
          • SMAWK??(放dp里?)
          • (待填)
        • 凸规划
      • 拟阵??
        • 拟阵基础
        • 拟阵交,并??
        • 广义拟阵??
    • 构造算法
      • 算术法(直接做的,经典的简单问题)
      • 状态-递推法(状态/递推类构造)??
      • 子问题法(倍增/分治类构造)??
      • 模式法??(解空间太大且整体研究太困难,从问题中取出特殊的一类模式只考虑该模式上的解)
        • 图上构造????(以及其它组合对象的经典技巧?)
        • (zig-zag 的例子)
      • 表示法??(组合表示和代数表示)
        • 组合的例子
        • 数论的例子
        • 代数的例子
      • 随机法??
  • 随机-近似
    • 引入:散列问题
    • 随机算法
      • 随机算法概念
        • 随机算法正确性和复杂性
        • 随机的分类(蒙特卡洛那些,按哪里用了随机分的)
        • 随机算法的分析????(太难了)
      • 散列
      • (待填)(包括各种经典模型)
      • 去随机化??
    • 近似算法
      • 近似算法概念
        • 近似比,近似算法的正确性和复杂性(以及任意参数近似算法)
        • 近似算法的分析????
      • 一些经典困难问题的近似算法
      • (待填)
      • 去近似化
        • 近似估计和微调
        • (待填)
        • scaling(同时也是分治方法)??
        • 数值拟合(算法学术界超级热门方法)
          • (普通的例子)
          • (zld筛,数论)??
          • (zak筛,数论)??
    • 随机和近似算法的联系????
  • 算法范式(算法的方法总结篇,不重复叙述上述大章节本身的核心思想。主要是一些到处都有用但 OI 没有一大类专门问题的算法思想。他们和上面的大章节没有本质区别。)
    • 迭代-增量-微调(贬为奶龙!)
    • 离线-在线;记忆化??(移入数据结构)
    • 均摊;信息量估计
    • 限界估计;剪枝
    • 参数复杂度问题??(移入计算模型,或省并。虽然OI也有很多给复杂度选主元的情况。)
    • (待填。)

其它数学

  • 代数-分析
    • 基础算术
    • 线性空间
    • 多项式和形式幂级数
      • ??
      • 卷积及其算法
        • (基础概念)??
        • 卷积反演
          • 子集反演(含二项式反演等)
          • 最值反演
          • 单位根反演
        • 卷积算法
          • FWT
          • FFT
          • 半在线卷积
          • 子集卷积
        • 分治乘和张量分解
          • 分治乘
          • 张量分解
        • DFT 的结构和推广
          • 有限交换半群
          • 群(??太难了)
      • 复合
        • 拉格朗日反演??
        • ??
      • 全序和最值
      • 偏序和格
      • 序数??
      • 置换??
    • 点格
      • 整系数线性空间
      • 离散子群??
  • 概率-统计
  • 组合计数
  • 数论
  • 博弈论
  • 计算几何

计算理论

  • 计算模型
  • 问题类和归约
  • 信息论和通信

附录

  • 前置数学知识名录
  • 程序实现:设计,测试,调试
  • C++ 语言和计算机系统知识技巧(如卡常数)
  • 计算机和人工智能工具在学习中的使用
  • 学习方法讨论
  • 对其余算法问题类型的简介,以及对希望学习计算机科学后续知识读者的建议
  • 推荐博客笔记,和参考文献

内容大纲已知issue

  1. 交互题放哪?通信题放哪?组合模式[pattern]和adhoc放哪?已解决。
  2. 组合计数的组合意义,概率方法……组合计数太繁杂了,怎么放?
  3. 计算模型包含函数式,交互式等简单介绍。
  4. 没有大类算法作为基础的方法,其概念本身放入算法范式总结篇介绍。比如限界法(计算前先估界剪枝以降低复杂度,例如先预处理出最优决策在某个小范围内)等。
  5. 多大程度上简省那些OI只有引用没有发展,且基本独立的偏门内容?例如博弈论,代数图论?初步结论:尽量少保留,对于前置知识太难的重要结论(如矩阵树定理)不讲动机只讲证明,对于足够讲动机的(如SG函数)则讲。问题是像 nimber 和 surreal number 之类的要不要全部删除?
  6. 算法部分是按范式/动机分类的,但是不应该割裂 OI 的专题知识点分类。OI 原本的专题应该尽量保持连续。例如:OI 中的“DP”是枚举-状态-递推的一大半和子问题-分治-倍增-递归的一小半。包括整体维护在内的 DP 优化也应该在此叙述。DP 模型也应在此叙述和 DP 应用有关的部分,尽管组合性质本身在离散数学部分中介绍。每个 OI 专题主题完整地写入其所属的最大一个分支(例如 DP 归入枚举-状态-递推),而其它分支中作为基础上的补充不要另起炉灶。是否应该直接把所有 DP 都塞进 DP,其余地方需要时最多用到个别例题?如果如此,像排列计数的状态技巧之类和组合对象关系紧密的怎么办?组合计数的这个问题甚至比 DP 还严重得多,怎么处理?目前看还是全塞。
  7. 在合作编写时,每个章节/每个人都写完整自己的内容,不要从一开始就考虑简省在其它章节中出现的部分。在大致完成之后再审稿省并重复并改为引用。例如数据结构中用到的分治。
  8. 在每个大中小章节中,原则上,总的方法论的论述应该放在最后,但从最一开始应该从具体问题和方法/动机开始推导。我们这种大纲容易过度抽象,尽量从具体例子引入推导避免这一点。
  9. practical问题:如何对待实现细节方面的知识?如何对待算法常数优化技巧?(例如zkw线段树之于线段树,压位分块之于四毛子,斜二进制之于树上倍增)如何对待计算机系统和编程语言层面的常数优化(如指令级并行)?

关于学习顺序:我觉得可以在附录和目录给出一些推荐顺序,但书本身还是按这个知识点框架顺序组织。

工作计划

  1. 在2025年底前完成我编写的部分的细致的纲目设计,并划分OI已经成文总结的知识点(含技巧)的联系。并且完成离散数学和算法部分各四五小节初稿以验证编写方式。
  2. 在2026年2月底前完成两三个章节的初稿作为例子。并开始作为讲义初步试用。
  3. 在2026年3月底前完成绝大部分章节写作人员的招募(我本人负责总内容的约一半多,其余我不擅长的内容招募人员负责)。以及所有细致的纲目设计。
  4. 在2026年7月底前完成一半的(OI中较核心的部分)章节初稿,开始作为讲义初步试用改进,并开始整理习题。
  5. 在2027年7月底前完成全部的初稿包括习题选择的初稿。所有章节开始作为讲义初步试用。
  6. 在2027年内定稿。

需要的外围协助工作:

  1. 帮忙收集OI的技巧套路知识点放到目录对应位置的桶里(包括常见但没名字的)
  2. 当人形题库,帮忙找符合条件的OJ例题(现成AI工具不能单独解决此问题)
  3. 帮忙审阅,特别是看写的是不是人话(特别需要一些OI水平没那么高但关注教学的人)
  4. 帮忙收集公开高质量学习资源的推荐。
  5. 帮忙造思考题或提供想法。特别是那些偶尔想到的不太实用/重复造轮子的新东西非常合适。思考题比较类似大学算法课的思考题讨论,每个思考题围绕一个技巧/数学概念/动机等小套路展开,用于补足编程题不太能表达的内容。思考题一般建议给同学几天内的空闲时间自行分组讨论最后写下想法。一般是基于一组算法问题步进编写,其中有至少一个 OJ 题或经典数学问题。

工作计划issue

  1. 协作平台问题。overleaf?Google Docs?飞书?直接github维护markdown文件夹?能用就行。

对这个框架或者编写原则有建议,补充或意见的请直接回复,复杂讨论可加入QQ群 435253885,十分感谢你的想法!

外围工作,其他工作的友链

LCA 的省选 NOI 长训二周目(2025)招生公告

2025-09-04 23:56:47 By liu_cheng_ao

LCA 的省选 NOI 长训二周目(2025)招生公告

LCA 的 OI 课堂开课辣!

fa025fd8c420225402faf6e7df41ed2e

2025 年 9 月 24 日起,LCA 的第二届省选 NOI 长训将在「山东省潍坊市」举行。第一期时间至 NOIP 前(拟)11 月 24 日。

第二期时间为(拟)12 月初(NOIP 后)至 2 月底(省选前),跳过 CCF NOI 冬令营和春节所在周和前后半周。

本次长训将会以线下全日制集训形式进行,每年一届,省选前分为二期,每期约两个月,以 NOIP 和省选时间分段,省选后继续进行。由 LCA 实际主讲,并且有多名蚂蚁国神秘嘉宾担任命题、助教和教务等工作。其中,部分节假日或比赛前会有短期集训,期间会有更多高水平旅客讲课和紧凑的模拟赛。


目前,在 NOIP 以上的省选、NOI 水平的学习过程中,同学主要通过大量刷题、模拟赛训练来提升实力。在遇到困难和瓶颈时,缺乏科学的方法去分析具体的知识、学习情况和应对策略,往往只能粗略地增加某一类型的刷题数量,或者尝试在自学和同学交流的过程中自行领悟一些算法和数学方法。

仅有的几个省选 NOI 长训,也是基于这些传统的讲课、刷题、模拟赛、同学自学交流开展的,缺少具体的教学方法帮助选手高效发现问题和提升深层次的理解和解题能力。

不过,近几年的 OI 同学们已经发展和引入了不少一般性的算法知识理论和教学方法。我们也有幸为 OI 社区的学习资源做出一些贡献,用学术方法改进 DP、优化(包括贪心)、构造、字符串等知识的深入理解,引入组合模型和计算理论等提高同学们研究和解决算法问题的能力,尝试题解补全、算法数学练习、问题改编研讨等新的教学技术和形式,并在往届长训营以及近年各省省队集训等课程中得到初步验证。

因此今年我们计划继续开展长训课程,邀请全国各地达到一定水平并计划冲击省队 NOI 的选手进行更为科学的长线训练。


↓↓↓ 来点大家想看的东西啊 ↓↓↓

IMG_3729.png

参加第一届长训营的 30 余名同学在 2025 年 NOI 中获得 2 金 10 银 4 铜,祝贺你们!


一些教学研究的笔记 https://loj.ac/d/4518

299f518daea1adc6d8518d47e59dda3a

测试赛

本次长训入营将更多参考平时训练情况,不过想打模拟赛的同学欢迎参与测试赛。测试时间和地址与报名联系获取,可自行选择。

请公平参赛。请勿在测试赛期间与人讨论、上网搜索题目或用 AI 辅助写程序等。一旦发现违规行为即失去资格。另外,注意比赛规范和时间策略,一定不要放弃部分分!

版本更新预告(最新)

  • 鉴于新一年同学水平提升(金银牌见多识广的同学),我们限制了专题课时数,提升了思考题/研讨以及模拟赛数量,并增加了更多思维练习。
  • 未参加互测或交流分享的同学需完成思维练习,从思考题、题解补全、记录新做法、整理数学知识点/小知识点/技巧等形式中选择。
  • 模拟赛数量增加为每周 3 场。
  • 增加了对同学个人训练过程的指导。

教学改进(往期)

省选/NOI 难度 传统教学 本次教学
学科体系 零散的算法知识点和题目 基于数学和算法科学的体系,带学生理解问题的实质和研究方法
教学内容 只有算法模板、变体和数学概念、例题 还包括描述和研究问题的数学模型、算法设计方法等
教学方式 讲课+刷题+模拟赛+答疑 还包括多种系统性解决问题的数学思维练习和研讨,如问题改编等
解题方式 以题感为主,方法靠自学领悟 理解数学方法,稳定记录和推进对问题的认识
作业题单 - 尽量覆盖各种OI中的技巧和应用
模拟赛 - 有编审对题目质量和难度进行把控,保证每场训练的有效性,避免低效题目如思维难度低的大代码毒瘤题、超纲的偏题怪题等。有公开原创月赛。

日常训练采用讲练结合的模式,全日制上课,有理论课、交流研讨课、晚自习(有答疑老师),并安排体育活动,劳逸结合。

课后作业除了常规训练题单外,增加了算法数学练习。

交流研讨课注重算法数学练习题讲解讨论,鼓励学生进行好题分享、算法想法分享和解题交流等,另外还会开展题目研讨课,对题单或模拟赛题目进行深入研究,通过改编等方式探究各种问题的一般性推广,并讲解相关 OI 应用和学术拓展知识,增进学生对知识的理解和问题模型的研究能力。

基本信息

  • 时间 第一期时间为 2025 年 9 月 24 日到 NOIP 前(拟)11 月 24 日。每周三到周一下午上课,周一晚上和周二休息。后续期数另行通告。

  • 地点 山东省潍坊市,线下全日制集训,位于学校内。

  • 教学团队 刘承奥(蔡德仁/LCA/CommonAnts)主讲,另有多名 NOI 水平助教参与工作。此外,有多名 NOI 金银牌高水平同学共同学习。

090e2a2d7d61c6f49554018d16bb117d

招生信息

  • 招生范围 招收全国 NOIP 250 分或同等水平及以上,或已经学习省选基础的同学(考虑到距离上次比赛时间已经较长,不要求过往比赛成绩,主要看平时训练情况,也可参加入营测试),并且家庭和学校支持接受全日制线下集训。

  • 招生人数 总人数不超过30人。

  • 报名方式 按期报名,一期起报。有意向同学可以填写问卷:问卷链接

  • 学习费用 按期收取,根据不同基础成绩享受不同优惠,多人团体报名另有优惠。详情请在填写问卷之后咨询。

  • 奖学金 根据 2025 年 NOIP 和 2026 年省选/NOI/IOI 成绩设有奖学金。详情咨询获取报名收费标准附录。

    • 上一届奖学金最高的同学获奖 1.3 万元
  • 教学基金 勰码已出资成立教学基金,专项补贴部分有经济压力的同学顺利完成营地训练计划,可用于缴纳学费、住宿费、承担生活费等在营期间的学习、生活基本支出。受资助同学需要承担部分建设 OI 社区公开学习资源任务和教学任务(教学可选在退役后进行),以推动 OI 发展以及营地教研、积累教学经验。具体细则和申请流程见公告。

报名&联系方式

c8b63adf03f91528f709f7bc8bbd2bb6

UOJ Σ* Round #1 题解

2025-04-13 23:37:58 By liu_cheng_ao

UOJ Σ* Round #1 题解

写在前面

由于第二题原本的题目描述并不对应解法,且原本的题目表述是更为困难的问题,第二题题面应该进行修改。然而,发现这一点时比赛时间已经接近结束(我在复核题解证明的时候发现的错误),因此我们不得不遗憾地宣布,由于这一问题,我们现在对第二题的题目描述进行修改,并且本场比赛将不会计分(unrated)。

最开始的第二题游戏规则是这样的,没有现在这样的多轮操作:

首先艾莉芬在棋盘上放置一些带颜色的积木。然后蔡德仁可以对棋盘进行任意次操作,然后交给艾莉芬再进行任意次操作,之后棋盘会进行左、下两次操作把所有积木收拢到左下角。

这是我没有做足够的验证和数学证明中的失误造成的错误,再次向各位参赛选手深表歉意。

彩色括号

  • 题意、题面、题解:liu_cheng_ao
  • 标程、数据:WeLikeStudying

思路

问题研究对象是满足条件的括号序列:整体合法且删掉每种单个颜色之后都合法,那么考虑怎么判断一个括号序列是否满足条件。

括号序列合法当且仅当:

  1. 左右括号个数相等
  2. 所有前缀和非负(将 () 分别视为 $+1,-1$)

分别考虑:

  1. 由于整体左右括号个数相等且删掉红色之后左右括号个数还是相等,作差可以得到红色左右括号个数相等。同理每个颜色都如此。
  2. 考虑某个位置 $i$ 的前缀和,设红绿蓝的前缀和分别是 $a,b,c$,那么 $a+b,a+c,b+c,a+b+c\ge 0$。可以发现当 $a+b,a+c,b+c\ge 0$ 同时成立时,全部相加可得 $2(a+b+c)\ge 0$。所以 $a+b+c\ge 0$ 这个条件不用单独考虑。

所以总的条件是:

  1. 每种颜色左右括号个数都相等。
  2. 删掉每种颜色得到的前缀和分别非负。

这是判断条件。现在我们再考虑如何用最少的修改次数让一个括号序列合法,发现:

  • )( 一定是前若干个 )() 一定是最后若干个 (。可以调整证明。
  • 所以可以贪心:如果某种括号多,那么先改那种括号到数量平衡。然后从外往里每次将第一个 ) 和最后一个 ( 一起修改,直到前缀和全部非负为止。这就是最小修改次数。

加上颜色限制后,每种颜色内部还是符合这个条件。所以我们不妨先把每种颜色都改到数量平衡,设这样改完后的整个序列是 $a'$。

然后设 $x_1,x_2,x_3$ 分别表示三种颜色从外往里多改了多少对括号。我们目标是最小化 $\sum x_i$。

考虑合法性对 $x_i$ 的约束,现在的约束只剩下删掉每种单个颜色时每个前缀和都必须 $\ge 0$。

对于前缀 $j$ 来说,颜色 $i$ 增加的前缀和是 $\min(x_i,A_{i,j},B_{i,j})$,其中 $A_{i,j}$ 是前缀 $a'[1,j]$ 中 ) 个数,而 $B_{i,j}$ 是后缀 $a'[j+1,n]$ 中 ( 个数。另外设 $C_{i,j}$ 表示一开始颜色 $i$ 在 $a'$ 的前缀和。

可以列出不等式组:

$$ (\forall k, j) \sum_{i\ne k} (C_{i,j}+\min(x_i,A_{i,j},B_{i,j}))\ge 0 $$

将 $\min(\cdot,\cdot)\ge 0$ 拆开成 $\cdot \ge 0\land \cdot \ge 0$ 的形式,全部整理完以及合并同类项后可以得到一个不等式组:

$$ (\forall S\subsetneq U, S\ne\emptyset) \sum_{i\in S} x_i\ge C_S $$

其中 $U$ 表示所有颜色的集合 $\{1,2,3\}$,$C_S$ 是一个算出来的由 $S$ 决定的常数。

所以整个问题就是在这个约束下最小化 $\sum x_i$。因为颜色很少,三维空间上每个限制是一个平面,直接在每个面上都双指针枚举判定其它限制下的最优解即可。当颜色数更大时可以当成较一般的整数规划问题。

三种颜色的约束是在这个图的形状上求离原点曼哈顿距离最近的点:

图

算法

按照思路所说,先做让每种颜色左右括号数量平衡必要的修改得到 $a'$,然后枚举前缀算出 $A,B,C$ 数组,合并算出不等式组。

三种颜色的情况下,可以看成三个形如 $x_1\ge \cdot\land x_2\ge \cdot\land x_1+x_2\ge \cdot$ 的三段折线的二维偏序约束进行合并。两两枚举用双指针算出它们相交的折线,然后第三个约束在折线上的效果是约束折线只能取前一半。枚举所有折线上的点更新答案即可,一共 $O(n)$ 个。

或者你可以直接把它当成实数线性规划手算答案公式然后向上取整,在本题三种颜色的特殊情况下这是对的。

时间复杂度:$O(n)$

扩展

根据思路,显然我们可以做更多颜色的情况。设颜色数为 $k$,复杂度则为 $O(nk+ILP(k,2^k-2))$,其中 $ILP$ 是整数规划复杂度。枚举约束子集的朴素暴力算法复杂度不超过 $O(nk+2^{(2^k)})$。

本题考虑出四种颜色的情况,但鉴于选手的体验并没有这么做。

部分分

如果你没有发现不等式组,可以用双指针和区间数据结构算出每两种颜色的约束。(没有不等式组不容易发现约束只有三段,但至少可以发现是二维偏序上的阶梯型)

然后仍然可以 $O(n)$ 合并三个二维偏序约束算出答案。

时间复杂度:$O(n\log n)$

如果你只发现了一部分性质,可以做更前面的部分分。

积木对战

  • 题意、题面、题解、锅:liu_cheng_ao
  • 标程、数据:Yanami

思路

问题给了一个上下左右的操作方式,我们要研究它。不妨用 $LRUD$ 的序列表示操作过程。

观察问题并手玩一些例子,发现:

  • 显然相邻的 $L,R$ 会抵消,相邻的 $U,D$ 也会抵消。抵消之后操作序列中 $LR$ 和 $UD$ 只能交替出现。奇数位置和偶数位置是两个子序列,分别只有 $LR$ 和 $UD$。
  • 另外,形如 $RDR$ 或者 $RUR$ 这种片段,第二个 $R$ 没有效果(一个 $R$ 之后只要没有 $L$ 所有积木都是靠最右的),可以消掉。同理,$L,U,D$ 都如此。
  • 所以可以推出消到最简的操作序列按下标 $\pmod 4$ 恰好分别是 $L,R,U,D$ 四种操作。实际上,长的操作序列只能是不断重复“顺时针转圈” $LURD$ 或者“逆时针转圈” $LDRU$。

那么一个操作序列的基本效果是 $LURD$ 的不断重复。可以发现,在操作两步之后,所有积木都到了角落,之后如果只考虑积木的存在而不考虑颜色,那么所有有积木的位置是确定的(以下用“形状”来称呼所有积木的位置集合)。我们记每行积木个数的数组为 $\{r_i\}$,每列积木个数的数组为 $\{c_j\}$,那么 $LRUD$ 依次是给这两个数组中的一个升序/降序排序而另一个不变。而一旦积木堆积到了角落里,之后无论怎么操作积木都只能堆积在角上了,这种情况下知道了 $\{r_i\},\{c_j\}$ 就能唯一确定形状。

加上颜色之后,转一圈总的效果就是在积木之间进行一个置换,对于固定的角上堆积的形状来说,置换是确定的,设为 $P$,可以算出。顺时针($URDL$)和逆时针($RULD$)对应的置换恰好互为逆。

(到这里我们可以解决 [ROI 2024] 2026 (Day 1) 这一问题。)

我们会发现,只要积木已经堆到了角落,那么后续它怎么操作都能逆回去。所以堆积在左下角的方案数是置换 $P$ 作用于最终状态所能得到的所有不相等的状态种类数,也就是 $\lvert \langle P \rangle (A)\rvert$,其中 $A$ 表示最终的棋盘状态。这可以算出置换然后每个置换环上颜色列的最小正周期(复制一倍然后KMP求最大border)算出环的周期再求最小公倍数(筛法求出每个质因子次数)来得到。

然后我们要考虑不到一个周期的情况。要保证无论蔡德仁如何操作艾莉芬都能操作,所以一个必要条件是初始局面 $LD$ 和 $DL$ 两种操作得到的形状必须相同。

可以得到以下条件:

引理 1 一个矩阵 $LD$ 和 $DL$ 形状相同,当且仅当存在一行或一列为全空或全满,且删去这行/列之后的子矩阵的 $LD$ 和 $DL$ 形状相同。

  • 充分性:通过操作的定义证明原来的结果等于删去这行/列后子矩阵的操作结果加上这行/列的结果,然后归纳。
  • 必要性:假如不存在,那么每行每列都既有空也有积木,则 $LD$ 后第一列必定全满,$DL$ 后第一行必定全空,左上角这一格矛盾,必然形状不同。

然而,在此基础上,满足这个条件的局面在 $LD/DL$ 操作后得到的颜色分布有可能不同,且不能通过 $P$ 置换互换。所以不能直接用形状的方案数和颜色置换的方案数相乘!

反例:

010     100     100
234 [LD]200 [DL]300
050     534     254

计算出 $P$ 可以发现第二行第一个和第三行第二个位置是不会变的,所以不能通过 $P$ 互换两者,这说明该矩阵不是后面两个矩阵的合法解!

一开始的做法给这一点做了伪证,并且没有做足够的暴力验证。

做法认为:

一个初始局面是符合题目要求的,当且仅当:

  • 它可以通过不断删去当前全空或全满的行/列删到空。(形状条件)
  • 它在 $LD$ 之后得到的颜色分布可以被最终状态的置换生成。(颜色条件)

所以认为原问题答案等于形状的方案数乘以颜色的方案数。具体来说,形状的方案数等于 $\{r_i\},\{c_j\}$ 数组重新排序能得到的不同数组的数量,颜色的方案数如前文所述。

因此,实际上题目应该这样安排游戏规则:艾莉芬先操作一次,再让蔡德仁染色。但这样仍然需要给答案增加一些分类讨论和常数系数,因此被迫修改成现在的题面。对于现在的题意来说,这个做法是对的。

然而,原问题的困难性也没有得到证明,并且可以发现在 $LD/DL$ 之后的颜色分布可通过 $P$ 置换的情况是有一定规律的,原问题未必就没有做法。

算法

(对于没改之前的题面是假的)

形状的方案数:先算出 $\{r_i\},\{c_j\}$ 数组,然后根据数组里每种数的数量组合数计算。

颜色的方案数:算出最终状态上 $URDL$ 作用的置换 $P$ 然后求每个置换环上颜色列的最小正周期(复制一倍然后KMP求最大border),算出环的周期,再求最小公倍数(筛法求出每个质因子次数)。

两者相乘即为答案。

时间复杂度:$O(n^2)$

程序校验

题意、题面:OldDriverTree, liu_cheng_ao

题解、标程、数据:OldDriverTree

算法 1

每次暴力模拟,总时间复杂度 $O(nm)$,空间复杂度 $O(n)$。

期望得分 5 分。

算法 1.5

考虑对暴力算法进行极限卡常,但是本题操作本质串行,无法使用指令集优化。

这里介绍一种对指令集的通用攻击手段:计算连续访问数组的 L1 缓存缺失量。

强制在线会导致遍历数组时发生大量的 L1 缓存缺失。

为了卡常到极限,利用取模生效次数很少的性质,可以将 $a$ 数组和 $l$ 数组预处理的时候进行合并,这样对于每个位置,只会进行 3​ 次 ​8​ 字节的数组访存。

评测机的 CPU 的 L1 缓存行大小为 32B 的数据缓存和 32B 的指令缓存,每个核心的 L1 缓存总大小为 32KB 的数据缓存和 32KB 的指令缓存。L1 缓存命中时需要约 $4\sim5$ 时钟周期,缺失时需要约 $12\sim14$ 时钟周期。(这段是问 deepseek 的,该数据大致复合正常 CPU 的表现)

如果暴力算法可以通过,则 1s 处理遍历数组时发生的 L1 缓存缺失次数为 $10^5\times 5\times10^5\times 3\times 8/32/10=3.75\times10^9$,由于 CPU 的频率是固定的,所以对时钟周期进行计算可以发现该数据远远超过 CPU 访存极限。

不过对于数据范围较小的测试点,有优化后的暴力算法获得了非平凡的分数。

期望得分 5~15 分。

算法 2

针对 $d_i=0$ 的情况,观察发现取模最多进行 $O(\log v)$ 次,因为每次取模都会导致 $v$ 减半。

考虑每次使用数据结构高效找到接下来第一次该数会发生取模的位置,等价于给定 $x,v$,求 $x$ 后面最近的一个区间,使得区间包含了 $v$。

这个问题可以倒着从后往前维护持久化值域线段树,维护每个值最近被覆盖的时刻,每次加入一个区间的时候做区间染色。

于是对每个位置 $i$,我们有一个持久化值域线段树,支持给定 $v$,查询从 $i$ 开始 $v$ 第一次被覆盖到的时刻。

总时间复杂度 $O(n\log v+m\log^2v)$,空间复杂度 $O(n\log v)$。

期望得分 15 分。

算法 3

如果所有询问的 $R$ 都等于 $n$,有一种持久化平衡树做法。

先考虑简化的,没有 $l_i,r_i$ 限制,并且 $d_i=0$ 的问题。

倒着维护每个后缀的函数复合结果,$f[i][j]$ 表示从 $i$ 开始,初始是 $j$,经过函数复合后到 $n$ 位置的值是多少。

初始是 $f[n][i]=i$ 的恒等映射,使用所谓的 “整体DP” 的思路,还是从后往前倒着维护,每次在原函数复合结果 $f[i+1]$ 前加一个新的函数复合得到 $f[i]$ 时做一个区间复制。注意到这里需要将一个区间变成另一个区间复制多次,这个可以用倍增合并的方法实现单次 $O(\log v)$。

特别需要注意的是,对于持久化 treap 来说,区间复制 $k$ 次的倍增合并是 $O(\log^2v)$ 的,而对于其他拥有更加优秀性质的平衡树(如 WBLT,AVLT),该操作是 $O(\log v)$ 的。

图

这样可以 $O(n\log v)$ 预处理出每个后缀的持久化平衡树,支持每次 $O(\log v)$ 查询给定 $x$ 和 $l$,求 $x$ 经过 $[l,n]$ 区间函数复合后的结果。

再考虑如果有 $l_i,r_i$ 的限制,并且 $d_i\neq 0$ 该怎么办。可以发现持久化平衡树功能非常强大,区间的限制可以通过每次对 $f[i]$ 只修改其 $[l_i,r_i]$ 部分,其他部分保持不变来实现。$d_i\neq 0$ 可以通过每次对 DP 数组做一个区间平移操作实现,可以用持久化平衡树的操作简单实现。

针对 $R=n$ 的情况,总时间复杂度 $O(n\log v+m\log v)$,空间复杂度 $O(n\log v)$。

期望得分 35 分。

算法 4

回顾算法 2,持久化值域线段树功能受限无法进行区间平移和复制操作,考虑将其换成持久化平衡树来支持更强的操作。

于是倒着从后往前维护持久化平衡树,维护每个点最近被覆盖的时刻,每次的操作有区间染色,区间复制,分裂合并等,都是持久化平衡树支持的操作。

对每次查询,使用预处理好的数据结构每次 $O(\log v)$ 找到最近一次取模的位置,需要取模 $O(\log v)$ 次。

总时间复杂度 $O(n\log v+m\log^2v)$,空间复杂度 $O(n\log v)$。

期望得分 55~75 分。

算法 5

我们发现对于 $R=n$ 我们可以每次 $O(\log v)$ 查询出答案,所以可以对序列分治建立线段树,对线段树的每一层,问题变成 $L=1,R=n$ 的子问题。

每次查询需要按顺序找到 $[L,R]$ 区间的 $O(\log n)$ 个线段树结点,将 $v$ 依次代入得到经过区间函数复合后的结果。

这个方法可以顶层分块,底层分块,将线段树变成多叉线段树来极大地减少常数。

顶层分块:可以发现线段树的根结点的没有用的,只有 $L=1,R=n$ 的查询才会用,所以可以不建立。继续分析可以发现线段树的最上面几层如果拆掉后,会减少预处理复杂度,少量增加查询复杂度。

底层分块:可以发现线段树的叶子结点是没有用的,如果建立的持久化平衡树,则每次查询是 $O(\log v)$ 的,还不如暴力。于是可以底层区间很小时直接暴力计算答案。

多叉线段树:可以发现线段树加上底层分块和顶层分块后二叉就不优了,于是将线段树改为多叉的。

利用右儿子:可以发现线段树结点可以直接从其右儿子处继承过来持久化平衡树,然后只需要将左儿子的部分插入即可。

图

利用左侧查询的优势:可以发现询问的部分如果是某个线段树结点的后缀,则可以不用暴力,而是用持久化平衡树的一次查询代替。

图

总时间复杂度 $O(n\log v+m\log^2v)$,空间复杂度 $O(n\log^2 v)$。

这个算法没有利用取模的特性,所以不优,在其他没有好的性质的题中是已知的最优做法。

利用以上技巧极限卡常后,期望得分推测为 55~85 分。

算法 6

我们考虑使用 “全局平衡” 的思想,类似于树链剖分套线段树的那种问题,每次查询如果需要在 $O(\log n)$ 个子问题上花费 $O(\log n)$ 的代价二分,导致复杂度是 $O(\log n) \times O(\log n)=O(\log^2n)$,如果将两种二分的结构套起来,构造出一种常数层减半的结构,就可以做到 $O(\log n) + O(\log n)=O(\log n)$。

我们在这个问题上,尝试将一开始的持久化平衡树的做法进行拓展,使得其可以进行区间查询,并且将第二,四种暴力做法的思想结合进去,即利用每次只会发生 $O(\log v)$ 次取模的特性。

图

我们在持久化平衡树上维护每条边的边权,有两种颜色的边,分别是红色和黑色。红色的边的含义是下方结点是某次取模导致的区间复制复制产生的,黑色的边的含义是正常持久化平衡树的边。

每个叶子结点到根结点的路径上最多只有 $O(\log v)$ 条红色的边,因为每走一次红色的边相当于找到了一次发生取模的事件,取模的性质保证只能发生 $O(\log v)$ 次取模。同时由于持久化平衡树是平衡树,所以可以保证每个叶子结点到根结点的路径上最多有 $O(\log v)$ 条黑色的边。

具体实现的时候,我们需要对每条红色的边记录下这条边是序列上哪个位置产生的,持久化平衡树的重新平衡(如旋转)仅限于对黑色的边,对红色的边是不做重新平衡的。平衡操作可以看做是产生新的边,以及将原本两条新的边压缩为一条边。由于我们是通过红色的边来找到每次取模的位置的,所以重新平衡的时候对红色的边做平衡操作会使得找取模位置的时候少找了一些,只能对黑色的边做操作。

每次查询 $[l,r]$ 区间,输入 $v$ 时,先在 $l$ 位置的持久化平衡树根结点上开始查询 $v$,在查询的过程中每次走一条红色的边则意味着发生了一次取模,走黑色的边则是为了保证持久化平衡树的深度所必须走的。这样我们可以用 $O(\log v)+O(\log v)=O(\log v)$ 的时间复杂度找到 $[l,r]$ 区间查询时所发生的所有取模事件。在递归查询的过程中如果发现走到了一条时间 $>r$ 的红色的边,则不需要继续递归了。

其实可以进一步解释本题做法,我们需要维护一个 DAG 结构,使得从任何点出发,该 DAG 深度是 $O(\log v)$ 的。虽然暴力的计算图的 DAG 深度是 $O(n)$ 的,但是我们只关心取模的位置,所以对于不是取模的操作可以将其合并在一起来减少 DAG 的深度。利用持久化平衡树深度以及取模次数的性质,可以构造出一个满足我们要求的 DAG 结构,每次查询本质上是在预处理好的深度 $O(\log v)$ 的 DAG 结构上进行 DFS。

本做法对于其他持久化平衡树做法有显著优势,因为其他做法需要多次查询持久化平衡树,本做法只需要一次查询,虽然本做法的平衡树由于“全局平衡”的性质所以常数比正常平衡树大。

总时间复杂度 $O((n+m)\log v)$,空间复杂度 $O(n\log v)$。

期望得分 100 分。

UOJ Σ* Round #1 公告

2025-04-02 16:41:39 By liu_cheng_ao

UOJ $\Sigma^\ast$ Round #1 将于 4 月 13 日星期日晚上 17:00 举行!比赛将进行 5 个小时,共三道题,和 UOJ NOI Round 赛制相同。

这是 UOJ 第一场 UOJ $\Sigma^*$ Round,NOI 难度,欢迎大家来玩!

UOJ $\Sigma^\ast$ Round 是 LCA 主办的系列比赛,希望大家参赛愉快。

在形式语言中,$\Sigma^*$ 表示“所有”字符串的集合,你能从无数字符的海洋中找到问题的答案吗?

比赛链接:http://uoj.ac/contest/96

出题人:liu_cheng_ao et al.

参加本次比赛将有机会获得 LCA 的神秘礼品!前三名均可获得礼品。

除此之外特殊获奖条件的 SHA256 码是 48405573d9ac7a841e4860fab6036961bd8a2e7404027595e7a84b47c7771b6b,比赛结束后将公布条件。

附启:你可以加入 LCA 的教学研究 QQ 群 435253885


赛后结果更新

特殊获奖条件公布:三道题得分均大于0的选手中总分最低的,如有并列就取最后一次提交最晚的。

比赛消息更新

由于第二题原本的题目描述并不对应解法,且原本的题目表述是更为困难的问题,第二题题面应该进行修改。然而,发现这一点时比赛时间已经接近结束(我在复核题解证明的时候发现的错误),因此我们不得不遗憾地宣布,由于这一问题,我们已经对第二题的题目描述进行修改,并且本场比赛将不会计分(unrated)。

这是我没有做足够的验证和数学证明中的失误造成的错误,再次向各位参赛选手深表歉意。

礼品仍然按照原成绩进行发放。

fa025fd8c420225402faf6e7df41ed2e

共 18 篇博客