2024-7 #1 我看见一匹丑马有了双翼 飞进了七彩的云里
我看见一匹丑马有了双翼
飞进了七彩的云里 --- 《丑马》
T1.【候选队互测2022】枪打出头鸟
线性基求交:对于两个维数 \(\le W\) 的线性基,我们可以在 \(O(W^2)\) 的时间内求出这两个子空间内的交的基。也就是选出尽量多的、线性无关的、能被 \(A,B\) 同时表示出的数。可以依次对每个 \(B_i\) 看它能否被 \(A \cup \{B_1,B_2,\cdots \cdots,B_{i - 1}\}\) 的子集异或出来。若行,则将此方案中属于 \(A\) 的子集的异或和加进交的基里。
有了这个东西之后这个题就 very easy 了。就可以直接求出前缀线性基的交然后二分,单次询问复杂度 \(O(W \log n)\)。然后我们发现本质不同的不同的线性基最多只有 \(W\) 个不同的线性基。所以可以做道 \(O(W \log W)\)。
然后我们继续优化,可以记录每一位主元在求交时被去掉的时间,然后回答时算出把 \(x\) 表示出的主元的最早去掉时间即可。最终的时间复杂度为 \(O(W)\)。然后这题略微卡常。
T2. 赵云八卦阵
假如操作完后的序列为 \(b_1,b_2,\cdots \cdots,b_n\),则 \(b_i\) 的值就是 \(a_1,a_2 \cdots \cdots c_{i - 1}\) 的线性基能表示出的值再异或上 \(a_i\)。如果 \(a_i\) 能被前 \(i - 1\) 个数的线性基表示出来,那么他就是 \(0\)。所以 \(a\) 数组中至多只会有 \(60\) 个非 \(0\) 元素。
然后从后往前考虑求出 LIS,对于 \(a_i = 0\) 的 \(i\),若 \(b_i\) 能被加入,那么这些就一定会被加入,应为它的取值范围不必任何 \(b_j(j < i)\) 小。所以只需要管 \(a_i \neq 0\) 的 \(i\)。
然后我们设计 \(dp\),\(dp_{i,j}\) 表示现在在第 \(i\) 位,已经有 \(j\) 个位加入了 LIS 之中,且所有为 \(0\) 的位均在 LIS 时,LIS 中最小元素的最大可能值。然后我们只需要在线性基中寻找小于某个数的第 \(k\) 大能够表示出的数即可。在某个 \(a_i = 0\) 的位置上已经不能将 \(b_i\) 加入 LIS 时,就直接更新答案即可。然后对于一次转移所需要的复杂度为 \(O(\log V)\)。
所以最终的复杂度为 \(O(n \times \log V + \log^3 V)\)。
T3. P5439 【XR-2】永恒
为了方便,我们定义没有 \(`\) 的就是原本的树上的,有 \(`\) 的就是 Trie 树上的。以及 \([u,v]\) 是 \(u\) 到 \(v\) 的路径,\(S\) 表示原树的点集。所以答案就是:
所以贡献就可以分成两种:
- \(lca(u,v) \neq u,v\):显然,包含 \(u\) 和 \(v\) 的路径一共有 \(siz_u \times siz_v\)。
对于这种情况,我们可以直接枚举 \(u\),然后在路径 \([u,root^{'}]\) 中的所有点加上 \(siz_u\),并且求出路径 \([v,root^{v}]\) 上所有点的和再乘上 \(siz_v\)。最后在除掉根的贡献即可。
- \(u\) 是 \(v\) 的祖先,此处定义 \(w\) 为 \(u\) 向 \(v\) 方向延伸的儿子,那么通过 \(u,v\) 的路径树为 \((n - siu_w) \times siz_v\)。
对于这种贡献,我们直接对于原树搜索一遍,到了一个 \(v\),考虑它到根节点的路径对 \(v\) 的贡献和。然后我们到了一个点 \(u\),然后枚举边 \(u \to w\),并给 \([u,root^{`}]\) 加上 \(n - siz_w\),然后向 \(w\) 走,当回溯时消去贡献即可。
但是我们发现这么做会有问题。在 \(u\) 子树内的 \(v\) 也被计算了。算重的 \((u,v)\) 均满足 \(v\) 在 \(u\) 子树内,所以把加的数改为 \(n - siz_w - siz_u\) 即可。
然后拿一个线段树维护即可,时间复杂度为 \(O(n \log^2 n)\)。
T4. [ARC117E] Zero-Sum Ranges 2
首先 \(k\) 就是满足条件 \(s_l = s_r\) 的 \((l,r)\) 的对数。然后我们钦定 \(c_i\) 为 \(i\) 在前缀和中的出现次数,那么答案就为 \(\sum_i (^{c_i}_2)\)。
显然的一个 \(s\) 就对应一个 \(a\)。所以我们对于 \(s\) 进行 dp。特别的,\(s_1 = s_{2n} = 0\)。
然后我们定义 \(dp_{i,j,k}\),表示已经处理了 \(i\) 位,\(j + 1\) 个连续段,计算出 \((^c_2) = k\) 的方案数。
转移考虑枚举一层点个数 \(x\),原本的每一个连续段都需要往左右填一个点,两个相邻的连续段之间也可以只填一个点将两个连续段以一个谷连接起来。
然后我们考虑连续段的变化。新的连续段变为 \(x - (j + 2) + 1\)。所以转移方程为 \(dp_{i + x,x - (j + 2),k + x \times (x + 1) / 2} \leftarrow (^{x - 1}_{j + 1}) dp_{i,j,k}\)。
那么最终的答案就是 \(dp_{2n + 1,0,s} + \sum^{2n + 1}_{i = 2} \sum^{n + 1}_{j = 1} \sum^s_{k = 0} dp_{i,j,k} \times dp_{2n + 1 - i,j - 1,s - k}\)。
T5. P9902 『PG2』模拟最大流
考虑前 \(i\) 个点的答案是 \(dp_i\),接下来我们考虑怎么转移。这会加入 \([i - k + 1,i]\) 到 \(i + 1\) 之间的一些边。然后我们就可以状压,把状态修改为 \(dp_{i,S}\)。S 的二进制下从低到高第 \(j\) 位表示,源点能否到达 \(i−j\) 这个位置。
转移的时候我们只需要枚举 \(i + 1\) 是否可以到达,如果可以,我们就不用割边,那么就为 \(dp_{i,S}\),如果不可以,那么对于 \(dp_{i,s}\) 中 \(S\) 每一个 \(1\),都要割掉到 \(i+1\) 的边,这个玩应可以先处理出来。我们定义 \(g_{i,S}\) 表示 \(S\) 为 \(1\) 的位置到 \(i + 1\) 的边权和,此时原 dp 的转移为 \(dp_{i,S} + g_{i,S}\)。