[QkOI#R1] Quark and Game 官方题解
E - Quark and Game
\text{Description}
给定
- 对于所有
b_i>0 的二元组,执行b_i\gets b_i-a_i ,花费p 。 - 对于所有
b_i>0 的二元组,执行\operatorname{Swap}(a_i,b_i) ,花费q 。
求一个花费最少的操作方法,使得所有二元组的
\text{Solution}
最优操作序列不会出现连续的交换操作。
最优操作序列一定是若干个不连续的交换操作将攻击操作划分,故我们将一个合法的操作序列写作若干个非负整数的序列,表示每次连续攻击操作包含的次数,特别地,若一开始就进行交换操作,则序列的第一位为
通过辗转相除法得到的操作序列一定是在排除了连续交换操作的情况下次数最多的操作序列。
考虑将一个二元组
- 当
a=b 时,终止递归。 - 否则,该二元组的序列是
\lfloor\frac{b-1}{a}\rfloor 的末尾接上(b-a\lfloor\frac{b-1}{a}\rfloor,a) 的序列。
进一步地,我们得到
考虑如何枚举可能的最优序列。
我们发现可以通过枚举 Trie 上的节点
考虑下一步要进行的攻击次数
从而促使我们设计一个 Trie 上的 DP。初始时我们在树根,表示一个空的操作。每次我们有三种选择:
- 攻击
max+1 次 - 攻击
mex 次,交换,攻击1 次 - 选择一个儿子,直接进入
这边要感性证明一个东西,我们选择一个儿子进入后,会让其它权值小于这个儿子的权值的儿子死亡,而权值大于这个儿子的儿子则会在交换后一遍攻击致死,从而我们只需关心这个儿子的子树。
显然这个做法的时间复杂度就是 Trie 的点数,但是这里由于字符集过大,我们可以用平衡树去维护儿子(当然也可以用 map,2s 时限就是给 map 开的)。考虑辗转相除得到的序列长度是