2021-2022 ACM-ICPC Brazil Subregional Programming Contest 题解

B - Beautiful Words

先对主串 \(A\)​ 复制一次(\(A' = A\times 2\)​)建出 SAM,然后对每个 \(B_i\in S\)​ 在自动机上跑匹配,得到 SAM 上每个点匹配到过的最长长度。跑完所有串后 parent 树上父子互相更新一下这个长度(瞎搓)。

然后我们看一看每个 \(A'\)​​ 长度为 \(n\)​​ 的子串,对应结点上的最长长度。然而这个仅仅是“最长能在 $$​​​ 中找得到子串的后缀” ,我们要的是子串而不是后缀。

考虑 \(A'[x-n+1:x]\)​​​​ 的一个最长后缀 \(T = A'[x-l+1:x]\)​​​​​ 在 \(\ S\)​​​​ 中作为子串出现过。那么之后 \(n-l\) 个位置都有接受 \(l\) 的贡献。容易忽略的一点是,再往后也会有贡献,形式是等差数列,因为每往后一次会截掉 \(1\) 的长度。这两种贡献用扫描线和 multiset 分别维护即可。

复杂度 \(O(n\log n)\)​​,应该有更优美的方法?

C - Creating Multiples

枚举 \(i:1\to L\),每次尝试减小 \(D_i\)。设减小量为 \(a\),那么有:

\[R - B^{L-i}\cdot a \equiv 0 \pmod {B+1} \]

其中 \(R\) 是当前数字 \(\bmod {B+1}\) 的结果。

扩欧解线性同余方程即可。

E - Escalator

直接模拟每个时间点即可。

G - Getting in Shape

考虑 AA...AB 这样为一个组件,那么由若干个组件拼接而成的解的方案数即为这些组件分别的方案数的乘积。

然后可以发现 \(x\)​ 个 A 的组件的方案数为 \(f_i\)​,其中 \(f_i\)​ 为 \(f_0=1, f_1=2\)​ 时的斐波那契数列的第 \(i\)​ 项。那么这样的话,\(10^{15}\)​ 内可用的组件数为大约七十多种。

考虑对一个数字 \(n\),用这些组件,从大到小试除方案数。注意大组件可用小组件不一定就不会用,最后 DFS 实现即可。

H - Handling the Blocks

将每个颜色分别排序,最后扔回原来位置观察是否有序即可。

J - Just Bootfall

wz 好强。感觉是很难想的网络流建模。

考虑最小割。我们建出边数为 \(m\) 的 \(n\) 条不相交路径,形如 \(S \rightsquigarrow T\)。第 \(i\) 条路径的第 \(j\) 条边容量为 \(U - P_{i,j}\)。其中 \(U\) 是一个足够大的数,保证每条路径只会割一次。

然后对于 \(C\) 的限制就很好搞了。对于一对 \(a, b\),我们在对应的两条路径上对应点相连,容量就为 \(C\):如果两者距离相差 \(d\),那么恰好会多割掉 \(d\)​ 条。

建完了。

K - Kathmandu

签到题。

L - Listing Passwords

并查集。对于一条限制 \([l, r]\),我们将对应位相连。最后检查是否矛盾,然后全 ? 的贡献 \(\times 2\) 即可。

如果翻转复制一边字符串,我们可以将限制转化为两个区间对应位相连的问题。这时一个 被我忘了的 套路:倍增。

首先建出 \(O(n\log n)\) 个点。对于两个区间,我们将其长度二进制拆分,然后区间分割为 \(O(\log n)\) 段分别相连。所有操作都过了之后,从大到小枚举 \(2^j\),若有 \((i, j) \to (f, j)\),那么将这一信息传递到 \(2^{j-1}\) 层,即连接 \((i, j-1)\leftrightarrow (f, j-1)\) 和 \((i+2^{j-1}, j-1)\leftrightarrow (f+2^{j-1}, j-1)\)。

然后就能直接查询了,复杂度 \(O(n\log ^2 n)\)。

M - Monarchy in Vertigo

阅读理解。离线建树,然后跑出 dfn。最后维护当前点集然后每次询问 dfn 最小的即可。

N - No Luck

不难转化为二维数点问题,然后就能树状数组扫描线做了,\(O(n\log n)\)。

上一篇:组织Golang代码


下一篇:LeetCode Weekly Contest 266