联合省选 2024 题解
魔法手杖
考虑判定答案是否可以大于等于 \(t\) 。
观察 \(a_i\oplus x<t\) 的情况,可以发现满足要求的 \(x\) 分为若干段:最高 \(u\) 位为 \(a_i \oplus t\) 的最高 \(u\) 位;接下来这一位 \(t\) 为 \(1\),且 \(x\) 取值为 \(a_i\) 这一位的取值;更低的位随意。
这事实上相当于:我们往 01-trie 上插入所有的 \(a_i\)(从高到低)。每有一个 \(t\) 的位为 \(1\),就交换同样深度的儿子,然后将左右儿子子树内的 \(a_i\) 打标记给对方。
在 01-trie 上 DFS,记录节点标号;当前的 \(x\)(前缀);当前的 \(t\);当前的位(从高到低);已经非法的水晶的 \(b_i\) 之和以及 \(a_i\) 的最小值。
如果是叶子情况很简单。否则,我们补全左右儿子,并考虑这一位 \(t\) 是否能取 \(1\):如果可以的话,意味着交换左右儿子,并打标记后,左右儿子至少有一方是仍然有解的,递归解决即可。
时间复杂度 \(O(nk)\) 。
虫洞
首先连边一定只会在同构连通块之间发生,用哈希判同构即可。
我们令 \((a,b)\) 为一个状态,表示有 \(b\) 个大小为 \(a\) 的同构连通块。对状态设计 DP:令 \(f(x,a,b)\) 表示 \((a,b)\) 后加 \(x\) 组虫洞的方案数。
考虑对 \((a,b)\) 新加一组虫洞,连边会产生如下影响:将某 \(k\in [1,b]\) 个连通块依次连成环,其中接环的地方(可以认为是最后一个连通块与第一个连通块之间的连边)影响了新的连通块是否同构。
即,一共有 \(a\) 种接环的方式,每种方式对应了不同构(但大小相等)的连通块。因此我们有如下转移方式:从 \(1\) 到 \(b\) 枚举 \(k\),对应新的连通块大小为 \(a\cdot k\) 。然后转移 \(i\) 次,对应不同重构方案:每次枚举一个 \(j\),对应拿出 \(j\) 个大小为 \(a\cdot k\) 的同构连通块。将上面这些东西背包一下,取第二维为 \(b\) 即是结果。
然后很多系数其实是可以提到外面的:我们令 \(f'(x,a,b)=f(x,a,b)\cdot \frac{i^j}{j!}\),对 \(f'(x,a,b)\) 的转移就简洁了很多。
重新观察过程,在枚举了 \(a,k\) 之后,我们实际上有多项式 \(G_k\),对应了每次转移的系数,其只有可能在 \(k\) 的倍数位置取值非 \(0\) 。做 \(i\) 次转移并背包相当于求 \(\prod_k(1+G_k^i)\) 。先 \(\ln\) 再 \(\exp\) 就很好处理了。
然后我们令 \(f''(x,a,*)=\ln f'(x,a,*)\) 。这样就只要在最开始取 ln 以及最后取 exp 。转移的过程就异常简单了:每次只要考虑 \(k\mid a\),从 \((a,b)\) 转移到 \((a/k,b\cdot k)\) 。
那么 \(f''\) 中 \(x\) 一维其实没必要了,我们只关心加入所有虫洞(设为 \(s\) 个)后,移动的 \(\prod k\) 是多少。换句话说,只要枚举结束状态 \((a\cdot k,b/k)\),并计算 \(s\) 轮中 \(k\) 带来的影响即可。
其中 \(k\) 的所有质因子都是独立的。对于一个 \(p^e\),\(p\) 之间是有顺序,不过我们可以发现要求的东西相当于 \({e+k-1\choose e}_p\),可以直接求。
于是,所有的 \((a,b)\) 只有 \(O(n\ln n)\) 种。我们进行 exp 与 ln 的复杂度是 \(O(n\ln n\log n)\) 。中间计算部分的枚举量是 \(O(n\ln^2 n)\)(即枚举 \((a,b)\) 后枚举 \(k\)),在 \(n=10^6\) 时也只有 \(\sim 10^8\),系数也可以预先处理出来,或者直接按质因子转移,可以做到更优的复杂度。
时间复杂度 \(O(n\cdot m+n\ln n\log n+n\ln^2 n)\) 。
重塑时光
我们只需要知道 \(f_k\) 即序列分成非空的 \(k\) 段合法的方案数即可。答案可以根据 \(f_k\) 直接计算。
令 \(h_s\) 表示 \(s\) 集合的合法拓扑序数。我们要选出 \(k\) 个不相交的集合 \(s\) 使得其并为全集,并且要求这些 \(s\) 形成拓扑图。这种方案对应了系数 \(\prod h_s\) 。
令 \(g_{i,t}\) 表示选了 \(i\) 个 \(s\) 交集为空、并集为 \(t\),为拓扑图的方案数。每次只需要删掉入度为 \(0\) 的 \(s\) 即可,可以通过 \((-1)^{i+1}\) 的容斥系数实现。于是令 \(f_{i,t}\) 表示选了 \(i\) 个 \(s\) 交集为空、并集为 \(t\) 且相互不连边的系数和。转移就是 \(g\) 卷上 \(f\) 带容斥系数的过程。
用插值去掉卷积可以去掉一个 \(n\)。
时间复杂度 \(O(3^nn)\) 。
最长待机
首先,可以删掉所有的非叶子白色点。接着观察得到:
- 一个长度为 \(x\) 的链,比任意多个长度为 \(x-1\) 的都主动。
- 长度依次为 \(x,x-1\) 的链与长度为 \(x\) 的链等价;长度依次为 \(x-1,x\) 的链比长度为 \(x\) 的链主动。
- 长度依次为 \(x,x\) 的链比长度为 \(x\) 的链主动。
由此,如果有若干条链的话,只要选择最长上升不下降子序列即可(包含单独的白色节点,我们认为长度是 \(0\))。然后:
- 如果一个黑色点的若干儿子都是链的形式,则其子树可以只保留最长儿子,而结果不变。
于是,我们有如下暴力:从 \(x\) 开始 DFS,如果是白色点,访问所有儿子;否则,求出子树最长黑色链,丢入序列末尾。最后求序列的最长上升不下降子序列的信息。
长度为 \(0\) 的白色叶子可以单独处理(用 set 找到 DFN 区间内第一个黑色点,用前缀和处理)。
我们只要维护 \(f_u\) 表示 \(u\) 向根的黑点个数,就可以单次 \(O(\log n)\) 求出 \(g_u\) 表示 \(u\) 向子树内最长的黑色链长度。
如果能维护 \(g_u\),答案就是对子树 DFN 区间启用所有黑色点的 \(g_u\) 后做单调栈(因为祖先总比后代优),可以单侧递归解决。
每次修改,对应的就是 \(u\) 向上若干步的祖先的 \(g\) 产生 \(\pm 1\) 的变化。考虑是树剖,因为标号不连续,每条链我们只更新最上方的黑色点,并取消下方所有黑色点的废弃(这是因为修改过后,下方黑色点可能会比上方黑色点的 \(g\) 更大,从而影响答案)。
每次询问时,只需要启用重链下方第一个黑色点即可。
于是修改次数是 \(O(q\log n)\) 的。但事实上可以通过 LCT 做到 \(O(q)\) 。
时间复杂度 \(O(q\log^3 n)\) 。