[Codeforces Round 1118 (Div. 2)] 题解

A. Odd Eraser

签子。

操作用人话翻译一下就是选一段长度为奇数的段然后把正中间的那个数删掉,然而对于除了 \(a_1\) 和 \(a_n\) 的数,我们都可以选择他左右的两个数从而达到把他删掉的效果,所以最终必然会留下的就是 \(a_1\) 和 \(a_n\)。

那么 \(\gcd(b_i) \mid a_1\) 且 \(\gcd(b_i) \mid a_n\),则 \(\gcd(b_i) \mid \gcd(a_1,a_n)\),从而 \(\gcd(b_i) \le \gcd(a_1,a_n)\),于是 \(\gcd(a_1,a_n)\) 就是 \(\gcd(b_i)\) 的一个上界,即所求的答案。

B1. Carrot Chopdown (Easy Version)

一次操作是好做的。

设 \(c_x\) 为 \(x\) 的出现次数,\(y\) 为最终要切割的长度,可以证明此时取切割位置 \(x=y\) 一定是最优的,因为此时所有 \(\ge y\) 的都可以贡献至少一个 \(y\) 出来,如果切割位置 \(x \ge y\),那么只有长度 \(\ge x+y\) 的才会贡献,显然劣于前者。

当我们切到 \(x=y\) 时,\(\ge y\) 的贡献值至少为 \(1\),长度为 \(2y\) 的贡献为 \(2\),所以 \(ans_y=\sum_{k \ge y} cnt_k+cnt_{2y}\),所有的 \(y\) 的 \(ans\) 取 \(\max\) 就是答案,直接做是 \(\mathcal O(n+m)\) 的。

B2. Carrot Chopdown (Hard Version)

原操作相当于从 \(x\) 处直接切断,如果最后让出售的 \(s\) 数量最多,则让所有 \(a_i\) 尽可能平均地分成若干个 \(s\)。而注意到每次操作相当于给二叉树上结点分叉的过程,而一个深度为 \(d\) 的树最多 \(2^d\) 个结点,等价于我们每次要切成类似 \(2^d \cdot s=2^{d-1} \cdot s+2^{d-1} \cdot s\) 的形式,则每一次切割切到 \(2^d \cdot s\) 一定是最优的,不难证明要从大往小操作。

尝试如上进行切割,则 \(a_i\) 的贡献除 \(a_i=2^k \cdot s\) 时贡献了 \(2^k\),其余的情况贡献为 \(\min(\frac{a_i}s,2^k-1)\),从而所有 \(i\) 的贡献都是 \(\le 2^k\) 的,考虑前缀和处理出多少个 \(x\) 贡献了 \(y\),这样是 \(\mathcal O(n+m\log m)\) 的。

C. Far Cities

曾经学找直径的时候有一种方法,即任选起点 \(s\),找到离 \(s\) 最远的点 \(u\),找到离 \(u\) 最远的点 \(v\),则 \((u,v)\) 就是一条直径。

那么问题转化成如何通过尽可能少的询问找到最远点,考虑维护当前最远距离 \(l\) 和对应的点 \(u\),贪心的对于每一个 \(v\),如果 \(\operatorname{dist}(u,v)>l\) 就一直扩大 \(l\),否则停止并更新答案。这样总询问次数应该是 \(\le 3n-3\) 的。

D. Magic Tiles

设 \(dp_i\) 表示覆盖到第 \(i\) 个区间前的最大答案,则 \(dp_{i}=\max_{\exists [l,r] \supseteq [j,i)} \left(dp_j+100^{100^{i-j}}\right)\),注意到有 \(100^{100^{i-j}}\) 这种巨大无比的数,因此需要使用高精,此时加法和取 \(\max\) 都是 \(\mathcal O(n)\) 的,而网格只有两列,所以这样是 \(\mathcal O(n^2)\) 的。

E. DivMEX

感觉官解最后一段讲的就不是人话啊,严肃理解 @He_XY 的优化过程。

注意到 \(x \nmid \operatorname{lcm}(a_l,a_{l+1},\dots,a_r)\) 等价于 \(\forall i \in [l,r],x \nmid a_i\),即 \([l,r]\) 中不能包含 \(x\) 的倍数,贪心地选两个 \(x\) 的倍数中间的段肯定是不劣的,此时我们只需要检查是否所有 \(<x\) 的数都不合法即可,大概这样做是 \(\le \mathcal O(n^2 \log n)\) 的。

考虑优化检查 \(<x\) 的数是否合法的过程。检查是否合法等价于查询 \([1,x-1]\) 内是否所有数均为 \(\operatorname{lcm}(a_l,a_{l+1},\dots,a_r)\) 的因数,预处理 \(a_{i}\) 的所有因数扔到线段树里维护,将所有询问按照 \(r\) 排序并把 \(i \in [1,x-1]\) 的质数幂因数丢进去修改,那么 \(x\) 是否合法等价于最小的 \(<l\) 的数是否等于 \(x\) 即可,这样做 \(\le \mathcal O(n\log^2 n)\)。

F. Plus Minus Tree

设 \(f_{u,s}\) 表示当前结点 \(u\) 子树内 \(1\) 的个数为 \(s\) 的最小代价,暴力合并子树是 \(\mathcal O(n^2)\) 的。

然而注意到对于固定的 \(u\) 而言,\(f_{u,s}\) 是凸的。那么对于把 \(u\) 的子树合并的操作,实际上就是对两个凸包做 Minkowski 和,因此合并完也是凸的,此时使用启发式合并把小的合并到大的可以做到 \(\mathcal O(n \log^2 n)\)。

下面证明为什么 \(f_{u,s}\) 是凸的。

考虑数学归纳法,这里归纳假设 \(f_{v_i}\) 都是凸的。

那么根据凸包 Minkowski 和的性质,把 \(u\) 的所有子树 \(v_1,v_2,\dots v_k\) 合并完之后仍是凸的。对于当前 \(u\) 而言,\(u\) 子树内有 \(s\) 个 \(1\) 和 \(siz_u-s\) 个 \(-1\),那么 \(u\) 的贡献为 \(|2s-siz_u|\),不妨把加入 \(u\) 贡献前的代价记为 \(F(x)=\min_{\sum x_i=x} \sum_{i=1}^k f_{v_i,s_i}\),那么当前 \(u\) 的总代价就是

\[|2s-siz_u|+ \begin{cases} F(s-1) & a_u=1\\ F(s) & a_u=-1 \\ \min(F(s),F(s-1)) & a_u=0 \\ \end{cases} \]

此时我们只需要证明 \(\min(F(s),F(s-1))\) 为凸函数。由于 \(F(x)\) 为凸函数,则 \(F(x)\) 的差分 \(d_s=F(s)-F(s-1)\) 为单调不减,此时

\[\min(F(s+1),F(s))-\min(F(s),F(s-1))= \begin{cases} \min(0,d_{s+1}) & d_{s}<0 \\ d_s & d_{s} \ge 0 \end{cases} \]

单调不减,从而 \(f_u\) 为凸的,根据数学归纳法证毕。

posted @ 2026-08-29 23:53  constexpr_int  阅读(231)  评论(0)    收藏  举报