CF思维题做题记录-2
CF2600左右有趣的思维题做题记录-2
CF1725L. Lemper Cooking Competition
考虑最后所有炉灶的温度都非负,这相当于这个数组的前缀和数组递增。我们考虑一次操作对前缀和数组的影响(记前缀和数组为 \(S\)):\((A_{i-1},A_i,A_{i+1})\to(A_{i-1}+A_i,-A_i,A_{i+1}+A_i)\),即 \((S_{i-1},S_{i},S_{i+1})\to(S_{i-1}+A_i,S_{i}-A_i,S_{i+1})\)。然而我们注意到 \(S_{i-1}+A_i=S_i,S_{i}-A_i=S_{i-1}\),那么操作后相当于 \((S_{i},S_{i-1},S_{i+1})\),于是我们可以将一次操作刻画为选择一个 \(i(2\le i\le n-1)\) 并交换 \(S_{i-1},S_i\)。
这是一个经典的问题,答案即交换次数就是原数列的逆序对个数,可以用树状数组做到 \(O(n\log n)\)。然而注意到我们没有办法交换 \(S_0,S_n\),于是需要判断 \(S_0\) 是否是最小的,\(S_n\) 是否是最大的来判断是否有解。
CF1924D. Balanced Subsequences
先特判掉 \(k>\min(n,m)\) 的 corner case,显然不存在最长平衡子序列的长度为 \(2k\),答案为 \(0\)。
我们设 \(f(n,m,k)\) 表示恰有 \(n\) 个 (
和 \(m\) 个 )
,最长平衡子序列的长度 \(\le 2k\) 的序列个数。
-
\(k=0\),显然答案为 \(1\),此时的 \(f(n,m,k)=1=\binom{n+m}{k}\)。
-
\(k=\min(n,m)\),显然此时将所有括号随意乱排即可满足限制,则 \(f(n,m,k)=\binom{n+m}{m}=\binom{n+m}{k}\)
-
\(k<\min(n,m)\),我们可以考虑枚举第一位是
(
还是)
:- 如果第一位是
(
,因为 \(k<m\),所以后面显然会有多余的没有匹配的)
,这个)
总会和第一个(
匹配从而给答案 \(+1\),贡献为 \(f(n-1,m,k-1)\)。 - 如果第一位是
)
,显然这一位不会有贡献,那么贡献为 \(f(n,m-1,k)\)。
于是我们又转移式 \(f(n,m,k)=f(n-1,m,k-1)+f(n,m-1,k)\),根据我们的边界条件总是可以推出来 \(f(n,m,k)=\binom{n+m}{k}\)。
- 如果第一位是
综上,我们总有 \(f(n,m,k)=\binom{n+m}{k}\)。于是答案为 \(f(n,m,k)-f(n,m,k-1)=\binom{n+m}{k}-\binom{n+m}{k-1}\)。预处理阶乘和阶乘逆元可以做到 \(O(1)\) 查询。
CF1682E. Unordered Swaps
考虑一个大小为 \(k\) 置换环内显然恰好交换 \(k-1\) 次,且不存在环才可能使得交换合法且次数最小,因此题目中给出的操作连边后一定形成了森林。
考虑 \(i\to p_i\),显然我们唯一合法的交换次序是依次交换 \(i\to p_i\) 简单路径上的所有边,否则都会导致 \(p_i\) 无法回到原始的位置。考虑用有向边限制这个先后关系,那么将所有的 \(i\to p_i\) 限制完之后只需要进行拓扑排序就可以得到一个合法的解。
对于一条边 \((u,v)\),如果 \(u\) 的子树内存在需要到 \(v\) 的子树的点,显然这样的点最多一个,否则肯定不合法。对于 \(v\) 的子树内的点同理,因此 \((u,v)\) 最多被两条路径覆盖,那么暴力跳父亲限制即可,复杂度是 \(O(n)\) 的。
CF1970A3. Balanced Unshuffle (Hard)
考虑简单版的正序实现,显然可以直接排序做到 \(O(n\log n)\),但是这对我们后面没有什么启发,因此不妨更进一步考虑。首先我们要知道,一个合法括号序列可以表示一个树:(
表示进入一个子树,)
表示离开一个子树,我们可以通过这个过程唯一确定一棵树的形态。考虑我们怎么用这棵树解决排序问题:显然在处理一个字符时,当前所在的位置的深度就是这个字符的前缀平衡值,因此我们将这个字符留在该节点的最前面,然后根据字符种类选择进入一个子树还是离开这个子树。最后从根节点开始广搜,将每个节点上的字符依次输出即可,复杂度可以做到 \(O(n)\)。
接下来考虑反向,在刚才的过程中,我们发现除根节点外所有的点的第一个字符都是 )
,且剩下的字符都是 (
,并且个数等于儿子个数。这是因为每个节点在进入儿子时一定会留下一个 (
,在离开时一定会留下一个 )
,并且离开肯定是最后进行的。这启发我们利用这一点复原树的结构:我们采用广搜,依次扫描字符,如果字符为 (
,则给当前节点增加一个儿子;否则这个节点没有儿子了,直接退出即可。确定了树的结构后,我们可以轻松确定原字符串,复杂度是 \(O(n)\) 的。
值得一提的是,题目中提到的两个证明可以通过上述过程简单证明。
CF1720D2. Xor-Subsequence (hard version)
考虑有一个显然的 dp 设计:\(f_i\) 表示以第 \(i\) 位为结尾的最长合法序列长度,那么转移方程是显然的
考虑如何快速找到所有满足条件的 \(f_j\),可以对限制拆位,对于第 \(k\) 位,可能有:
- \(a_j\oplus i=0\) 且 \(a_i\oplus j=1\),此时所有的 \(j\) 的 \(f_j\) 都有贡献。
- \(a_j\oplus i=a_i\oplus j\),此时继续向下一位讨论即可。
于是我们维护 \(a_i\oplus i\),考虑转化上面的两个条件:
- \(a_i\oplus i=a_j\oplus j\oplus 1\land i=a_j\),此时所有的 \(j\) 的 \(f_j\) 都有贡献。
- \(a_i\oplus i=a_j\oplus j\),此时继续向下一位讨论即可。
不难看出可以直接用 Trie 树维护后向下走,对每一个节点维护这一位所有 \(a_i=0/1\) 的 \(f_i\) 的最大值即可,复杂度是 \(O(n\log V)\) 的。
CF1442D. Sum
直接做背包是 \(O(nk^2)\) 的,我们考虑发现一些性质。首先可以容易得到一个结论:最多只有一个序列没有选满。可以用反证法证明:假设有两个没有选满,比较两个序列的最后选择的值,设有 \(A_{1,p}<A_{2,q}\),于是可以考虑将 \(A_{1,p}\) 取消,进而选择 \(A_{2,q+1}\),由于递增的性质,这样一定不劣。并且由于递增,取消之后的 \(A_{1,p-1}\) 依旧小于 \(A_{2,q+1}\),这样重复操作直到一者选空或选满肯定更优,这样枚举哪个数组没有选满,剩下的数组就只用进行 \(01\) 背包了,总复杂度是 \(O(n^2k)\) 的。
现在考虑一个经典的分治思路:\(\text{Solve}(l,r)\) 表示正在求解 \([l,r]\) 区间,我们先将左区间 \([l,\text{mid}]\) 的所有数组放入背包中,然后调用 \(\text{Solve}(\text{mid}+1,r)\),接着还原背包,将右区间 \([\text{mid}+1,r]\) 的所有数组放入背包中,然后调用 \(\text{Solve}(l,\text{mid})\)。这样做的好处是当处理 \([l,r]\) 时,除这个区间外的所有数组都已经被放入了背包,这样我们只需要在 \([l,l]\) 处统计答案即可,复杂度分析 \(T(n)=2T(\dfrac{n}{2})+O(nk)\) 得到时间复杂度是 \(O(nk\log n)\) 的。
CF1545C. AquaMoon and Permutations
考虑有一些行是一定可以确定的:当 \(a_{i,j}\) 是第 \(j\) 列在唯一出现时,显然第 \(i\) 行一定要选。我们先将这些行选择了,那么和这些行的某一列相同的行肯定不能选,根据题目中保证的性质,我们至少能找到一行删去。接着我们继续寻找是否有能够确定的行直到找不到为止。
根据我们每次确定的行都会至少连带着一行删去,那么我们此时剩下的行数 \(\le\) 二倍的未确定行数。根据鸽笼原理,此时每一列的每一个数都恰好出现了两次,这说明我们可以将剩下的行分成两个拉丁方,所以我们此时可以任意选择一行,将方案数 \(\times 2\) 即可。
上面的过程都可以暴力枚举实现,复杂度是 \(O(n^3)\) 的。