A. Acronym
枚举每个单词判断即可。
B. Baggage
考虑两个包裹分别从 u 运到 v,中途没有同时运送两个包裹,则方案形如:
- 包裹 1 u→a1,空手 a1→u,包裹 2 u→b1,空手 b1→a1,包裹 1 a1→a2,空手 a2→b1,包裹 2 b1→b2,……,包裹 1 ak→v,空手 v→bk,包裹 2 bk→v。
可以发现这样的方案可以重新排列成:
- 包裹 1 u→a1→a2→⋯→ak→v。
- 空手 v→bk→ak−1→bk−2→⋯→a1→u。
- 包裹 2 u→b1→b2→⋯→bk→v。
因此代价不小于 2dis1(u,v)+dis0(v,u),其中 disc(x,y) 是从 x 到 y,只能经过容量不少于 c 的边的最短距离。
而 2dis1(u,v)+dis0(v,u) 显然是一个合法方案,因此只需将 u 到 v 连上距离为 2dis1(u,v)+dis0(v,u)、容量为 2 的边,然后求容量 等于 2 的最短路即可。
时间复杂度 O(n3)。
C. Cows
二分答案,转化为判定是否能够在 x 分钟内吃完所有的草。
按照 i 从小到大的顺序,维护如下的状态:考虑下标在 [i,n] 中的牛,且满足下列状态之一
- 存在不超过 2 个时间区间,牛 i−1 会在这些时间区间内帮牛 i 吃草。有两种情况:
- 如果在时间 t 吃完了所有了牛 i 的所有草,则牛 i 可以在 [t,x] 时间内帮牛 i+1 吃草。
- 否则,设剩余的草的数量为 a,则牛 i+1 需要在 [x−a,x] 时间内帮牛 i 吃草。
- 存在一个时间区间 [l,r],牛 i 需要帮牛 i−1 吃草。有两种情况:
- 如果牛 i 自己能够在 l 时间之前吃完所有草,设吃完草的时间为 t,则牛 i 可以在 [t,l] 和 [r,x] 时间帮牛 i+1 吃草。
- 否则,设在 l 时刻剩余的草的数量是 a,则牛 i+1 需要在 [l−a,l] 时间内帮牛 i 吃草。
如果最终牛 n 不能吃完所有的草则说明答案大于 x。
时间复杂度 O(nlogH)。
D. Diminishing Fractions
分数的分母显然不超过 M=lcm{1,2,…,n},而分子最小是 1,因此可能的最小值是 1/M。我们考虑通分,在 mod 意义下构造 1,然后只需减去整数部分即可(因为已知分子是 1,可以直接用浮点数计算)。
设 \le n 的所有极大素数幂分别为 p_1^{e_1},p_2^{e_2},\ldots,p_k^{e_k},则 M=\prod_{i=1}^k p_i^{e_i}。现在我们想要找到 a_i\in [0,p_i^{e_i}) 满足 \left(\sum_{i=1}^k a_i(M/p_i^{e_i})\right)\bmod M=1。
这可以通过 CRT 构造:我们希望 x\bmod p_i^{e_i}=1,所以令 a_i 为 M/p_i^{e_i} 在模 p_i^{e_i} 意义下的逆元即可。
因为 \sum n 很大但 N=\max n 不大,我们在每组数据中分别进行求逆,则只需按照 n 从小到大的顺序维护 \prod_{j\ne i}p_j^{e_j}\bmod p_i^{e_i}。每次增加一个素数幂时,都可以在 O(k)=O(n/\log n) 的时间内完成维护。
总时间复杂度 O\left(\frac{N^2}{\log^2N}+\sum n\right)。
E. Express Rotations
考虑一个指向序列开头的指针,初始在 a_1 之前。这样操作可以转化为指针循环向前移动、循环向后移动和删除指针之后的第一个数。
考虑设 \mathrm{dp}(v,i) 表示删除了所有 \ge v 的数,指针的位置在 i 的最小代价。我们可以认为只有需要删除一个数时需要移动指针,因此有用的状态一定满足 a_i=v,因此总状态数是 O(n) 的。
从 v+1 到 v 的转移,首先从之前所有有用的位置转移到所有 a_i=v 的位置,这只需要先转移到前后相邻两个位置,然后再正反分别扫两遍更新。计算从位置 i 向后移动到位置 j 的代价,也就是计算 [i,j) 中所有 \ge v 的数的总和,可以用树状数组在 O(\log n) 时间内计算。
接下来考虑删除所有等于 v 的数。可以发现指针的移动要么是先往前再往后,要么是先往后再往前。如果是先往前再往后,可以认为所有数都是在往后的过程中被删除,因此直接用指针移动的代价减去所有 =v 的数的总和来更新即可。如果是先往后再往前,因为往后移动的过程中,删除一个数不需要代价,但往前移动的过程中需要先移动到数之前再删除,所以有 v 的代价。我们可以将少的代价在往后移动的过程中计算,即从 i 移动到 j 的代价是 [i,j) 中所有 >v 的数的总和减去 v。这会导致一个问题:移动的代价可能是负数,导致一直在环上绕圈。这是因为,我们只有在第一次删除一个数的时候会带来总代价的减少,但直接在环上转移忽略了这个限制。一个解决方案是使用单调队列,限制只能往后移动 \mathrm{cnt}_v-1 次。
时间复杂度 O(n\log n)。
F. Frogs
考虑计算 p=n 的答案。令 b_i=a_{i+1}-a_i(下标都是 \bmod n 意义下的),即青蛙 i 要追的青蛙和它坐标的差。如果 b_i\ge 0,则青蛙 i 会向右跳,否则会向左跳。考虑 b_i 的变化,当 b_i\ge 0 且 b_{i+1}< 0 时会减去 2k,当 b_i< 0 且 b_{i+1}\ge 0 时会加上 2k。可以发现,在有限轮之后,所有的 b_i 都会落入 [-2k,2k) 内。此后 \{b_i\} 一定会进入一个循环,我们希望判断在一个循环内,青蛙的坐标是否不变。注意到当所有 b_i\in[-2k,2k) 时,b_i 的符号(负数还是非负)只和上一个时刻 b_{i+1} 的符号有关,因此在循环中负数的个数是始终不变的,因此我们只需判断负数的个数是否等于非负数的个数。
我们只需判断是否有 n/2=\sum[b_i< 0]=\frac{1}{2k}\sum(b_i\bmod 2k-b_i)。注意到 \sum b_i=0,而 \sum (b_i\bmod 2k) 是常数,因此只需判断是否有 \sum(b_i\bmod 2k)=\sum((a_{i+1}-a_i)\bmod 2k)=nk 即可。
对于所有的 p 计算答案,也只需要在 p 增大的时候维护这个和。
时间复杂度 O(n)。
G. Game MPO
将所有的 M 和 P、O 和 O 连边,则只需从所有大写字母开始 BFS 即可得到最终状态。
H. High Jump
最优策略可以表示成 a_1< a_2<\cdots< a_k,依次挑战高度 a_1,a_2,\ldots,a_k。分数的期望是 p_{a_1}a_1+p_{a_1}p_{a_2}(a_2-a_1)+p_{a_1}p_{a_2}p_{a_3}(a_3-a_2)+\cdots。令 a_0=0,这个式子也可以写成 f(i)=(f(i+1)+(a_{i+1}-a_i))p_{a_{i+1}},答案即为 f(0)。
考虑从后往前 DP,则 \mathrm{dp}(i)=\max_{j>i}\{(\mathrm{dp}(j)+j-i)\cdot p_j\},可以用凸包优化转移。
时间复杂度 O(n)。
I. Imbalanced Teams
显然最大值等于前 k 大的和减去前 k 小的和。在确定了选择的数的可重集后,只需乘上对应的组合数即可。注意如果两个队伍有相同的数,还需要计算分组的方案数,并且当所有数全相等时,两组是本质相同的,方案数需要除以 2。
时间复杂度 O(n)。
J. Just Zeros
考虑维护 f(S) 表示翻转的行的集合是 S 的情况下,还需要多少步能够将所有数变成 0。也就是翻转行后,每一列的 \min\{c,1+h-c\} 之和。通过 f(S) 可以在 O(2^h) 时间内计算答案。
如何在操作后维护 f(S):
- P 和 K 操作都只会影响一列,可以对每个 S 重新计算该列的贡献。
- R 操作只需将 f(S) 和 f(S\oplus \{i\}) 交换。注意需要打一个第 i 行取反的标记,在另外两种操作中需要用到。
时间复杂度 O((w+q)2^h)。
K. Kindergarten Square
通过两行的差可以求出 w,而 h 越大越好,然后判断是否满足条件即可。
L. Looping RPS
考虑对 s_i^\infty 建立 Trie,则三个人形成一个环当且仅当它们在同一个点的三个不同子树内。因此建立 Trie 后可以直接枚举 LCA 计算贡献。
建立 Trie 分为两步:排序,然后计算相邻串的 LCP 并建立笛卡尔树。
难点主要在于排序,直接按照 a+b< b+a 比较可能导致时间复杂度变为 \Omega(n|s|)。我们希望比较两个串的复杂度是 O(\min\{|a|,|b|\}),则总复杂度为 O(\sum|s_i|\log n)。不妨设 |a|\le |b|。如果 a 不是 b 的前缀则可以直接比较,否则我们需要求 b 和 b[|a|:] 的 LCP,这可以通过预处理每个串的 Z 函数后 O(1) 得到。
时间复杂度 O(\sum |s_i|\log n)。