Happybob's Interactive Challenge
Happybob's Interactive Challenge (aka. Trainig 28(2026.10.5~)
做法来源:我、hb、GPT、洛谷题解
难度按体感难度分类,每类内部按题单顺序排列。
Very Easy Problems
A. P14421 拉面比较
Sum: 擂台法
显然存在 \(2n\) 次的方法。考虑初始对所有元素两两配对进行比较,那么 \(\frac n2\) 次之后,我们得到了 \(\frac n2\) 个备选最大值和 \(\frac n2\) 个备选最小值。分别进行擂台法即可。
B. QOJ11621 Vacant Seat
Sum: 二分法
特判 \(0\) 是空位的情况。剩下的,对于一个位置 \(m\),若 \([0, m]\) 之间没有空位,则 \(m\) 座位的性别是可以根据奇偶性得出来的。因此可以对空位进行二分。
C. P9599 木琴
Sum: 杂题
对相邻两个问一次,即可得到相邻两个的差 \(d_i\)。然后对连续三个问一次,这样就可以知道相邻两个 \(d_i\) 符号的关系。最后还原出来排列如果最小值在最大值右侧,则值域翻转即可。
F. P15366 Cave
Sum: 二分
考虑求出哪个开关对应了 \(0\)。我们翻转任意的开关,如果“最近可见门是否为 \(0\)”发生了变化,说明操作 \(0\) 的开关倍翻转了。因此可以在上面二分。后续操作也是一样的。
H. P9507 Popa
Sum: 笛卡尔树
观察到笛卡尔树是一个合法的解。因此直接按照笛卡尔树的方式建就行了。
Easy Problems
D. P10642 Art Collections
Sum: 排列循环位移
假设第一次询问 \(1 S\),第二次询问 \(S 1\),这样所有和 \(1\) 有关的逆序对全部反向。因此我们通过观察两次逆序对数量的差得知 \(1\) 的排名。
对于所有数,只需将一个排列的所有循环位移都问一遍就行了。
E. P3641 最大差分
Sum: 分块剪枝
首先花费 \(n+1\) 的代价对全局询问,获得值域区间 \([l, r]\)。显然答案 \(\ge \frac{r - l + 1}{n-1}\)。
将值域按 \(\frac{r-l+1}{n-1}\) 分成 \(n-1\) 块,每一块我们只关心内部的最大值和最小值。最后我们将得到的 \(2n-2\) 个数排序后求最大邻差即可。
总代价恰好为 \(3n\)。
G. P13015 Dat Bae
Sum: 分块
观察到特殊位置 \(\le 15\)。考虑对原序列按照 \(16\) 个分块,每个块内部填相同的值,块之间 \(01\) 交替。这样我们能问出每一块内有几个。
在之后的过程中,所有块内处理可以并行。对于一个块来说,我们可以按前后分成两半。将前半部分设为 \(0\),后半部分设为 \(1\),这样可以根据 \(01\) 的个数得出前后半部分各有几个。于是形成了分治的结构。总次数 \(5\) 次。
I. P14375 图书馆
Sum: 极大独立集
询问相当于告诉你其中有几本书是相邻的。
考虑求出一个极大的独立集 \(S\)(可以依次枚举每一本书,如果可以加就加),那么剩下的一定不存在连续三个未加入 \(S\) 的书。因此我们可以将剩下的划分成两个极大独立集 \(T, U\)。这样所有相邻边一定来源于不同的独立集。对每条这样的边二分即可。
J. P13612 组合动作
Sum: 观察限制
先用两次将第一个字符问出来。接下来尝试每次多问出一位。假设我们已知了一段前缀 \(S\),剩下还能出现的字符有 \(A, B, X\),则我们可以问 \(\overline{SAASABSAXSB}\),这样我们能通过一次询问问出下一位的值。
最后一位无法这样做,但是此时有两次询问机会,所以都问一遍就行了。
N. QOJ5531 ICC
Sum: 二分法、标号
每个时刻整个图都被划分成了若干个连通块。我们尝试将这些连通块(作为一个整体)不断分为两个部分 \(A, B\),直到新边两端不在同一侧。
考虑给每个连通块标一个二进制的序号,第 \(i\) 次划分的时候就以第 \(i\) 位作为划分依据。因为两个连通块序号不同,故一定会在某一次被分开。
被分开之后就可以在两边分别二分了,次数为 \(3\log_2 n\)。另一种做法是先二分出具体是哪两个连通块,再在连通块内部二分。可以证明这种做法也是 \(3\log_2 n\) 次的。
Medium Problems
K. P14395 神经衰弱
Sum: Hold、分讨
存在更优做法。
考虑对于任意三个数,我们对它们两两询问。如果得出的结果有两个相同,且与另外一个不同,容易说明那两次询问均包含的元素是它们当中的权值最小值。如果三个都相同,说明有两个数相同,且比另一个小。这个时候,我们选其中两个数和第四个数进行询问。可以发现无论如何我们都一定能确定这四个中一个的值。
这样对于前 \(2n-3\) 个数,我们都各花费了 \(3\) 的代价问出了它们的值。对于最后的 \(3\) 或 \(2\) 个数,可以借助已知的值进行分类讨论。总之不会超过 \(6n\) 次。
M. P15275 解读 Bug
Sum: 分治
先考虑 \(n^2\) 次怎么做。我们将 \(\overline{10\dots 0}\) 存入,这样读的时候,我们找到唯一一个 \(\text{popcnt} = 1\) 的值,那个就是 \(1\) 被转移到的位置。然后我们接着传 \(\overline{110\dots 0}\),等等。这样能做到 \(w = n, r = n^2\)。
但这个做法 \(w, r\) 太不平衡了,例如说我们为了算出第一位就读了 \(n\) 次。
考虑对前 \(64\) 为都传一个 \(\overline{0\dots010\dots0}\)。这样我们能把所有位分为两部分 \(L, R\)。然后向两侧递归。对于 \(L\) 来说,接下来的递归中我们将 \(R\) 对应的位全部设为 \(1\),这样就能识别当前在哪一层了,层之间也不会混淆。
代码实现稍有不同。
R. P3839 The Big Prize
Sum: 分治
我们将最低等级的视为普通点,其他视为特殊点。由题目条件,特殊点最多 \(470\) 个。且如果一个数两边有 \(\ge 31\) 个比它大的,则它一定是普通点。
考虑将所有特殊点都找出来。可以直接分治地找出所有点,毕竟每次可以知道左右有几个。最后我们对特殊点依次 check 看是不是最大的即可。
V. P14351 矿物
Sum: 分治、决策树
考虑这样一个分治结构:已知 \(S\) 中的所有矿物都对应了 \(T\) 内部的矿物,且目前 \(S\) 所有元素“是否在机器里”是相同的,我们要求出 \(T\) 具体对应了哪些矿物。
可以采取这样的策略:将 \(S\) 中部分翻转状态,然后翻转所有 \(T\) 中的点。这样可以根据 \(T\) 翻转时的变化量决定对应 \(S\) 中的哪一半。
具体翻转多少可以 dp。设 \(f_x\) 表示识别 \(x\) 个需要的最少次数,则有:
直接 dp 可以发现 \(f_n + 2n \le 10^6\),可以通过。
另外,猜测 \(f_n = C_1n\log n\) 且 \(x = n \times C_2\)。经过推导可得可直接取 \(x \approx 0.382 \times n\)。
Hard Problems
O. P15294 铁路
Sum: 排序
考虑先询问 \(0\) 到所有车站的距离。易得最近的是右侧第一个 D 类型车站。
对于剩下的车站,考虑将它们按照 \(0\) 到其的距离从小到达加入,并同时维护当前最左、右侧的车站 \(L, R\)(容易发现 \(L, R\) 的类型一定是 C、D)。
对于一个新车站 \(u\),询问 \(L, R\) 到 \(u\) 的距离 \(l_u, r_u\)。观察最优路线的结构,\(l_u, r_u\) 中一定有一个是坐标之差,另一者会在恰好一处折返。并且无论是哪一者折返,折返的位置都是确定的,记为 \(m_u\)。
如果 \(m_u\) 处已经有了已探明的车站,那谁折返就是确定的了。否则,如果 \(m \gt 0\),则 \(m\) 一定不为 D 类型车站;若 \(m \lt 0\),则一定不为 C 类型车站(这都与 \(L, R\) 定义、排序加入矛盾)。总之能唯一确定新车站的方向和位置。总询问次数 \(3n - O(1)\)。
Q. P7211 变色龙之恋
Sum: 观察性质
可以发现可以根据题目意思建出一个有两种边的图。对于颜色相同的两只变色龙,我们在它们之间连一条双向边。对于喜欢的关系,我们可以连有向边。注意这里颜色相同的双向边,和相互喜欢的对向有向边是不同的。
先考虑一个 \(O(n^2)\) 次询问的做法。对任意点对 \((u, v)\),返回值为 \(2\) 有两种可能。一种是它们之间没有任何边,要么是它们相互喜欢(对向边)。如果是后者,我们可以暂时忽略(毕竟我们确实也分辨不了)。这样每个点分辨出来的边的数量为 \(1\) 或者 \(3\)。
如果为 \(1\),那显然它与某一只相互喜欢。但至少我们直到识别出来的是颜色相同的双向边,直接得到了。否则,设它的三个邻居为 \(u, v, w\)。我们将其与 \(\{u, v\}, \{v, w\}, \{u, w\}\) 相互询问,可以发现一定有两次回答为 \(2\),一次为 \(1\)。为 \(1\) 的那次没有被包含的点就是当前点出边(也就是它的对象)。而入边会在另一端处理时被算出来,所以最后一条边就是颜色相同的边了。
考虑加速前面的过程。我们可以直接求出一个独立集 \(S\),然后让剩下的所有点在独立集内二分邻边。因为每个点度数 \(\le 3\),所以每次的独立集至少有剩余点数的 \(\frac 14\)。所以这个算法只会递归 \(\log\) 层。
总次数 \(O(n\log n)\),限制很宽松。
S. P14341 海狸的会面
Sum: 随机化、点分治
考虑对树进行点分治。但可以发现我们很难算出一个点在哪个子树。而且,随机选点进行点分治的复杂度是错的。
事实上可以发明“链分治”。对于固定点 \(u, v\) 和一个其他点 \(w\),Query(u, v, w) 返回的就是 \(w\) 到 \(u, v\) 链上的第一个点。因此我们可以随机选出两个点 \(u, v\),依此将当前连通块内所有点分成若干类,然后分别递归。注意还要将链 \(u, v\) 本身进行递归。
交互次数证明起来比较复杂,而且最坏情况大概率是错的。不过在大部分情况,结合随机选取链来看,表现还是非常优秀的。
T. P6766 有趣的旅途
Sum: 求重心、剥叶子
考虑链怎么做。显然可以交替地从两端删点。
假设以某个点为根,它有两个子树,且两个子树大小相差 \(\le 1\)。此时仍然可以采用链的构造:轮流删除一个子树中的最深点。
当有三个子树的时候也是一样的,每次删除不是上一个的最深的叶子。不过有特殊情况,就是当一个子树大小变成另外两个的和的时候,实际上已经退化成了两个子树的情况,此时就需要轮流删了。
可以发现上面的情况需要我们找到树上的重心。重心就是在以任意点为根时,子树大小 \(\ge \frac n2\) 中子树大小最小的点。之后再求出所有点的深度即可,次数 \(3n\)。
X. P14399 地牢 2
Sum: dfs 树上三进制标号
题目要求的那个东西,如果没有图还是很难做的。考虑把图问出来,最后跑一遍 Floyd 就行了。
考虑求出一棵 dfs 树。一开始的颜色可以当作是否访问过的标记,因此我们可以在 \(2n\) 步内建出来。
求出了树之后,我们可以给每个点标一下号。因为允许使用三种颜色,所以可以采用三进制分组。第 \(i\) 次操作中我们让每个点的颜色改为标号中的第 \(i\) 位值。然后对于每一条非树边,我们都可以花费 \(2\) 的代价探测另一端的值。这样仅需 \(2 (\log_3n + 1) \approx 14\) 倍的次数,在题目范围内。
但直接这么写是不行的,因为每条树边实际上贡献了 \(4\) 的代价。考虑利用建树时的颜色,将已经完成子树递归的点设成第三种颜色,这样每条非树边只会被记录一次。
Harder Problems
P. P9601 最长路径
Sum: 观察性质
先考虑在 \(D = 1\) 的时候求出一条长度为 \(\lfloor\frac{n}{2}\rfloor\) 的路径。考虑维护两条路径 \(P, Q\),然后依次加入每一个点。
对于当前点 \(i\),若 \(i\) 与 \(P, Q\) 的尾端 \(p, q\) 有直接连边,则可以加入对应的路径。否则,因为 \(p, q, i\) 至少存在一条边,此时 \(p, q\) 之间一定有边。所以可以合并 \(P, Q\),然后让 \(\{i\}\) 单独形成一条路径。
这样一共问了 \(2n\) 次,即使只用回答一半也超了。注意到这个限制大约是 \(1.5n + 2\log_2 n\),所以不难想到可以通过 \(3\) 次询问加入 \(2\) 个数。
假设接下来要加入 \(i, j\) 两数。先正常让 \(i\) 尝试加入 \(P, Q\)。如果加入了 \(P\),直接正常加 \(j\)。否则若 \(i\) 加入了 \(Q\),则 \(j\) 一定可以加入 \(P\) 或者 \(Q\)(因为 \(p, i\) 之间无边)。否则,我们询问 \(i, j\) 之间是否有边。若有,将 \(P, Q\) 合并后,视 \(\{i, j\}\) 为另一条路径。否则 \(j\) 与 \(p, q\) 均有连边,可以将 \(P, j, Q\) 合并。
这样我们成功在 \(1.5n - O(1)\) 次内问出了一条长度至少为一半的路径。
接下来,如果 \(P, Q\) 之间没有任何边,那直接就结束了。否则,我们先花 \(3\) 次判断端点处是否有连边,若有,则可直接连接。否则,由于 \(D\) 的限制,\(P, Q\) 本身还是一个环。因此此时可以直接在两个环上分别二分出两个点 \(u, v\) 使得 \(u, v\) 有边。这样就能连城一个大环了。
W. P6837 数蘑菇
Sum: 局部 ID-3 算法
假设我们已经知道了 \(A\) 个 A 类型蘑菇,那么我们可以直接在 \(\frac{n}{A}\) 次内把 A 的个数问出来。即去问 \([A, 1, A, 2, A, 3, \dots, A]\),这样相邻不同的数量 \(\div 2\) 就是其中 B 的数量。
取 \(A = \sqrt{n}\) 可得到一个 \(O(\sqrt{n})\) 次的做法,但显然过不去。
后面的部分没有什么优化空间,考虑优化前面的部分。即我们需要加速找到 \(A\) 个 A 类型蘑菇(对称的,求出 \(A\) 个 B 型蘑菇也是可以的)。
考虑采用局部 ID-3 算法。我们维护一个当前需要计算类型的蘑菇集合 \(S\),以及它们的备选状态 \(\mathcal{S}\)。每次若 \(\lvert S\rvert\) 太小,或者 \(\lvert \mathcal{S} \rvert\) 太小,就将下一个蘑菇加入 \(S\)。接下来随机 \(T\) 组询问,每次询问都计算一下询问结果的信息熵,取最大的进行询问。
经过乱仔细调参可以通过。具体参数可参考代码。
Y. P6541 即时战略
Sum: 动态点分树
可以发现链部分的限制比较特别,大致是 \(n + \log\) 次。
考虑将所有点以随机的顺序加入图中,这样只有平均 \(2\ln n\) 次会拓展链(即其他点都被别的点顺带加入了)。每次拓展链都有 \(\frac 12\) 的概率会浪费一次询问(用来定向),所以浪费的次数为 \(\ln n\)。可以通过。
对于普通树的情况,考虑在树上“二分”去找到一个点挂在哪个点下。显然我们可以点分治。点分治的询问次数显然是正确的,但算法本身的复杂度太大了。
考虑类似紫荆花之恋地维护动态点分树,当一个子树大小 \(\gt\) 上一层的 \(0.7\) 倍时就重构。这样我们以一点询问上的常数换来了正确的算法复杂度。
由于这个只需要维护树的结构,没有别的信息,所以好写一点。
Z. P15285 城镇
Sum: 重心、“变种摩尔投票”
显然所谓的“中心城市”就是带权重心。考虑求出 \(0\) 的最远点 \(u\),然后求出 \(u\) 的最远点 \(v\)。这样 \(D = d(u, v)\) 就是直径。但是我们还要求出半径。
事实上重心一定在 \(0 \leadsto u\) 路径上。对于另外一个点 \(x\),\(x\) 到路径上的位置,位于 \(u\) 往 \(0\) 走的 \(d_x = \frac 12(d(x, u) + d(u, 0) - d(0, x))\) 距离处(注意不能算成到 \(0\) 的距离,因为 \(0\) 不是直径端点)。易得半径就是 \(\min_x\max(d_x, D - d_x)\)。
至此我们已经花费了 \(2n\) 次询问。接下来是判断一个中心是否还是非带权重心。显然可能有两个中心,位于 \(D - R\) 和 \(R\)。设 \(r_x = d(x, y) - d_x\),那么我们可以根据 \(r_x\) 和备选距离 \(R'\) 的大小关系分为两类。其中 \(\lt, \gt\) 是和直径端点同一个子树,\(=\) 是其他子树。首先如果三类大小都 \(\le \lfloor\frac n2\rfloor\) 那直接就合法了。否则,如果直径端点子树有 \(\gt \frac n2\) 个点,那这个备选就不合法。
可以发现,两个中心只有至多一个需要后续的判断。
对于两个不在直径端点上的点 \(x, y\),它们在同一个子树内,等价于 \(r_x + r_y \ne d(x, y)\)。
于是现在问题变为,有 \(n\) 个点,颜色未知。每次可以花费 \(1\) 的代价问两个点是否颜色相同。最后要判断是否存在某一色有 \(\gt \frac n2\) 个点。
摩尔投票可以做到 \(2n\) 次,完整原题就需要 \(4n\) 次询问,无法通过。
考虑这样一个算法。维护三个等价类集合 \(C_{(\text{urrent})}, T_{(\text{rash})}, L_{(\text{arge})}\)。初始将所有点视作大小为 \(1\) 的等价类加入 \(C\)。然后进行若干轮,直到 \(C\) 为空。
每一轮中,我们不断取出 \(C\) 中的两个等价类 \(u, v\)。如果 \(u, v\) 相同,就合并加入下一轮的 \(C\),否则把两个都丢弃(加入 \(T\))。如果 \(C\) 大小是奇数,最后会剩下一个,直接加入 \(L\)。
若存在严格众数,观察转移过程可以发现,它的一部分会成为 \(L\) 中最大的等价类。因此我们再用 \(L\) 最大的等价类去和其他的 check 就形了。
可以发现中途每合并两个连通块,最后 check 的次数就会减少 \(1\)。因此整个过程只需要比较 \(1.5n\) 次。总次数 \(3.5n\),可以通过。
Strange Problems
L. P15284 天平
Sum: 决策树
一共有 \(6! = 720\) 种排列,每次询问有 \(3\) 种不同的回答。因此至少需要 \(\lceil \log_3 720 \rceil = 6\) 次。观察到 \(3^6 = 729\) 只比 \(720\) 大一点点,所以每一次搜索必须要非常均匀。
因此可以直接搜索决策树,大部分情况被直接排掉了。实际上搜决策树的时间都不超过半秒钟。
U. P3777 考拉的游戏
Sum: 缝合怪、分治、dp 求决策
本题依赖关系:五依赖二、四依赖三
考虑最小值怎么求。随便在一个点放一个,对方没选的就是最小的。
然后是最大值。考虑在每个位置都放一个,这样可以得到最大的 \(50\) 个。然后在最大的 \(50\) 个上分别放 \(2\) 个,可以得到最大的 \(25\) 个。然后在上面放 \(4\) 个,可以得到最大的 \(9\) 个。最后分别放 \(11\) 个,就能得到最大值了。
然后是比较。考虑在 \(0, 1\) 处各放 \(x\) 个,其余不放。可以发现只有大致满足 \(\binom{x}{2} \in [\frac{p_0, p_1}{4}, p_1]\) 的时候(假设 \(p_0 \lt p_1\))才能分辨出来。因此取 \(x \in \{1, 2, 3, 5, 7, 10, 13\}\) 即可在上面二分,需要 \(3\) 次。
然后是 \(w = 2n\) 的排序。其实就是在 stable_sort 的基础上,将比较函数特殊实现一下。在需要比较的两个上面各放 \(n\) 个,则对方会恰好选择其中较大的那一个。
最后是 \(w=n\) 的排序。考虑分治,假设当前已经知道了 \([l, r]\) 对应哪些位置。考虑在它们上面各放 \(x\) 个,那么对方一定会选择其中较大的若干个。只要对方的选择不是平凡的(即不是全选或全不选),我们就将其划分成了两个子问题。是否非平凡可以复制实现一下交互库来判断。这样只需要 \(n-1\) 次询问就够了。
AA. P13867 Unique Activites
Sum: 混入其中 /kx
求最短出现一次的子串,直接再后缀树上搞搞就可以了。


浙公网安备 33010602011771号