CF1774 题解

发布时间 2023-08-29 15:57:41作者: Matutino_Lux

A

考虑在所有 \(0\) 前添加正号,在 \(1\) 前轮流添加正负号即可。

B

首先根据抽屉原理,我们可以取出最多的颜色,个数记为 \(mx\),然后其余颜色可以填在 \(mx\) 的两两中间,最少要有 \((mx-1)(k-1)\) 个空位。
但是只是必要的,而不是充分的。考虑有多个最大值的情况,发现这些不是作为分界点的最大值没法全都用,要少用一次。所以对于每种这样的总数要减去 \(1\)

C

我们对于每种序列,倒序考虑。考虑最后一次战斗,如果是 \(1\),那么一定有一个比他小的数存在,\(1\) 就不合法。否则如果是 \(0\),那么要有一个比他大的存在,\(n\) 就不合法。
扩展这个思路,考虑当前最后一个 \(01\) 连续段,如果有 \(x\) 个,相当于前/后 \(x\) 个数是不能选的。当出现 \(0\)\(1\) 时,就没有关系了。

D

无解当且仅当 \(1\) 的个数不被 \(n\) 整除。
考虑用 set 维护每一行,每次选出最多的和最少的两行,交换位置使得每次较多的那个减少,较少的那个增多。直到有一行达到最终状态,即不能再增多减少。这样每次至少使一行合法,保证了复杂度。

E

定义 \(f_{u,0/1/2}\) 表示以 \(u\) 为根的子树,只考虑第一个棋子/第二个棋子/第一个与第二个棋子遍历完子树中的所有点回到 \(u\) 的最小步数。
转移的话,\(f_{u,0/1}\) 直接从子树中累加,然后加上进子树和出子树的 \(2\)\(f_{u,2}\) 则要考虑两种关键点的深度,来决定是否要两个点都要进入子树中。如果只有一种点且最大深度满足条件,那就可以只动一个点。

F

直接考虑 F2。
考虑将每次的操作形式化,注意到 \(3\) 把操作序列分成的若干段,那么有一棵满二叉树,深度越深操作顺序越前面。然后对二叉树做后续遍历。
考虑每一次 \(1\) 操作对答案的贡献。合法的贡献范围一定是该层从右到左一段连续的区间,考虑暴力怎么做,从根出发,如果右子树的 \(2\) 操作和可以让当前的操作保持大于 \(0\),那么往左子树走,否则往右子树走。贡献就是最终走到的点。但是这样每次复杂度 \(O(n)\) 考虑优化。
注意到一开始是一段连续的 \(\infty\),即肯定往右子树走,那么可以二分第一次往左子树走是什么时候。然后开始走,一直走到第一个子树和为 \(0\) 的位置,那么后面肯定只会往左子树走,这样每次至少答案减半(子树和指数级递增)。单次复杂度是 \(O(\log V)\) 的。

G

观察的个差式,考虑一种方案选择了 \([L,R]\),存在 \([l,r]\)\([L,R]\) 包含,那么所有选择了 \([L,R]\) 的方案数可以选择 \([l,r]\) 使得方案被抵消,所以舍去所有包含别人的区间。
这样剩下若干个左右端点单调递增的区间。考虑现在的 \(\mathrm{dp}\) 过程,记 \(f_{i}\) 表示覆盖到 \(y_i\)。那么转移的时候,如果当前的区间可以和倒二区间接上,那么选不选倒一区间都可以,方案抵消。所以此时就可以直接跳到第一个倒二区间接不上的位置。维护二元组 \((u,v)\),每次 \(u,v\) 都跳到第一个不接壤的位置。最后判断是否有一个位置的 \(y\)\(r\),那么答案为 \(1\)\(-1\)。否则为 \(0\)。若 \(u=v\) 的时候也是 \(0\)。有一些特殊情况特判一下就好。