2024.12 杂题记录(中)

目前状态:已退役

lg 模拟赛 D2T3

几乎场切了啊,但是数组怎么开小了。不想写了,摆烂贺个官方题解。

考虑模 \(m\) 意义下的前缀和数组 \(s_i\),那么一个限制 \([l_i,r_i]\) 实际是限制 \(s_{l_i−1}=s_{r_i}\)。 我们把钦定相同的位置用并查集缩起来,这样就划分了 \(\mathcal O(q)\) 个集合。对于这些区间端点划分成的段 \([L,R]\),每段内的方案数只和 \(s_{L−1},s_R\) 有关,更进一步的只和 \(s_{L−1}\) 是否等于 \(s_R\) 有关,我们设 \(s_{L−1}=s_R\) 时的方案数是 \(w_1\),不相等的方案数是 \(w_2\)。考虑怎么求 \(w_1,w_2\),对于中间任意填的长度 \(len\),我们可以枚举原数列中哪些位置为 \(k\),这样可以缩起来这些边,枚举有 \(i\) 个,差不多就是 \(\sum \binom{len}{i}k^{len-1-i}=\frac{(k+1)^{len}-1}{k}\)。需要考虑全部为 \(k\) 的情况,加上是否相等的方案数。

那么我们现在要解决这样一个问题,有 \(\mathcal O(q)\) 个连通块,我们要给每个连通块分配一个 \([0,k−1]\) 中的值,使得对于每个段 \([L,R]\),如果 \(s_{L-1},s_R\) 所在连通块被分配的值相等,就有 \(w_1\) 的贡献,否则就有 \(w_2\),我们要求所有分配方式的贡献乘积的和。 我们可以先求出所有 \(w_2\) 的乘积,然后把贡献修改为 \(w_1/w_2\) ,这样只需要考虑分配的值相等的连通块的内部贡献即可,可以预处理一个 \(g_S\) 表示如果集合 \(S\) 内部的连通块被分配了相同的数,那么内部的贡献是多少。

不考虑每个连通块的标号方式的话,是集合幂级数模板。

考虑优化,我们考虑钦定若干集合分配的数字相同,但不要求不同集合之间分配的数字不同, 这样子我们乘上 \(m\) 的集合个数次方即可,因此关键是求出系数,设为 \(coef_S\)。 用幂级数的语言描述就是 \(C=\exp D\),即 \(D=\ln C\),这里的 \(\ln\) 求法具体为:求出子集卷积的占位多项式并对其做 \(\ln\),因为范围很小可以暴力求 \(\ln\) 即可。 求出容斥系数 \(D\) 之后,最后的答案实际就是 \(\exp(mD)\),套用该过程即可。 最后的复杂度即为 \(\mathcal O(q^22^q)\)

二次离线莫队

  • 适用于:可以莫队;指针移动时修改时间较大。

模板是区间逆序对单根号做法。

考虑莫队的指针移动一共是 \(\mathcal O(n\sqrt q)\) 次,这期间计算贡献,会是一个单点对于一个区间的贡献 \(f(x,[l,r])\),令 \(g(I_1,I_2)=\sum_{i\in I_1}f(i,I_2)\)。注意 \(f(x,[l,r])\) 如果可以差分可以拆成 \(f(x,[1,r])-f(x,[1,l-1])\)。然后对于 \(ans([l,r])=ans([1,r])-ans([1,l-1])-g([1,l-1],[l,r])\) 而言,可以分开计算。

那么求 \(g(I_1,I_2)\) 的贡献与求 \(ans([1,x])\) 是独立的。对于求 \(ans([1,x])\) 而言,求出每个 \(x\) 对前缀的贡献后可以使用莫队处理。 然后考虑 \(g(I_1,I_2)\) 可以扫描线,由莫队指针移动的连续性,可以拆成 \(\mathcal O(1)\) 个操作。那么扫描线时就会是 \(\mathcal O(n\sqrt q)\) 次查询以及 \(\mathcal O(n)\) 次修改,可以根号平衡。

时间复杂度 \(\mathcal O(n\sqrt q)\)

lg 模拟赛 D2T2

上面那个是本题的前置知识。首先用一些数论推导来化简。

一个等式是 \(\varphi(xy)=\frac{\varphi(x)\varphi(y)\gcd(x,y)}{\varphi(\gcd(x,y))}\)。那么可以枚举两者的 \(\gcd\) 并施加莫比乌斯反演。令 \(f(x)\to \varphi(x)f(x)\),就有答案是形如 \(\sum \frac{d}{\varphi(d)}\sum[\gcd(a_i,a_j)=d]f(a_i)f(a_j)\)。最终可以化简成:

\[\sum_{T=1}^m\left(\sum_{d|T}\frac{d}{\varphi(d)}\mu(\frac{T}{d})\right)\sum_{T|a_i,T|a_j} f(a_i)f(a_j) \]

调和级数处理一下 \(g(T)=\sum_{d\mid T}\frac{d}{\varphi(d)}\mu(T/d)\) 就统计的是:\(\sum_{T}g(T)\sum_{T|a_i,T|a_j}f(a_i)f(a_j)\)

考虑利用数据随机的性质,每次暴力更新影响到的 \(T\),一个数的期望因子个数只有 \(\mathcal O(\log m)\)。处理询问可以考虑使用莫队,这样就有一个 \(\mathcal O(n\sqrt q\log m)\) 的复杂度做法。

注意到 \(m\leq 10\) 的部分分提示,可以考虑对不同的 \(T\) 施加根号分治。那么对于 \(T\leq \sqrt m\) 的可以直接暴力对于每个 \(T\) 前缀和做到 \(\mathcal O((n+q)\sqrt m)\)。对于 \(T>\sqrt m\),对于一个长度为 \(n\) 的数列,期望有 \(\mathcal O(n/T)\) 个位置是 \(T\) 的倍数,依旧考虑莫队,可以进行二次离线。由于 \(T\) 比较大且已经二次离线,那么就是 \(\mathcal O(n)\) 次修改以及 \(\mathcal O(n\sqrt q)\) 次查询。数据随机,修改的复杂度是正确的。视 \(n,m,q\) 同阶,时间复杂度 \(\mathcal O(n\sqrt n)\)

USACO 2024.12 T1

这是一个状压的形式,可以用集合的语言描述。考虑查询 \(a_i\),记其为集合 \(S\),全集为 \(U\)。那么考虑枚举 \(t=\text{popcount}(a_i\text{ or }a_j)\),那么等价于获取,所有 \(|a_i\cap (U/S)|=t\) 的所有 \(a_i\) 的信息。问题来到预处理:

  • \(f(S,r)=\sum_T[|S\cap T|=r]c_r\)
  • \(g(S,r)=\sum_T[|S\cap T|=r]c_rs_r\)

我们希望找出所有 \(K\subseteq S,K\subseteq T\) 的子集 \(K\) 的信息。考虑 \(K\subseteq S\) 作为查询,\(K\subseteq a_i\) 作为修改。设计一个容斥系数即可。考虑先提取出 \(r\),然后考虑容斥系数 \(coef_p\),容斥系数基于 \(p=|S|\)。那么令实际交集为 \(q=|S\cap T|\),就要求 \(\sum_{p\leq i\leq q}\binom{q}{i}coef_i=[p=q]\),显然有 \(coef_p=1\),而后可以用 \(\mathcal O(k^2)\) 的递推求 \(coef\)。子集加子集和容易用高维前缀和处理。时间复杂度 \(\mathcal O(2^kk^2)\)

USACO 2024.12 T2

闵可夫斯基和板子。

LOJ3155

  • boruvka 思想,代表元思想,图论思想,SCC 的性质。

对于四个方向相邻的格子集合 \(U\),串 \(D\) 的作用就是告诉你,对于一个位置 \(u\),有一些集合 \(S\subseteq U\) 满足一旦 \(S\) 集合均被染色,则这个格子也会被染色。可以 \(\mathcal O(2^{d}|D|)\) 的时间预处理出最长吹风时间,其中 \(d=4\) 表示网格图中每个格子相邻的格子数。于是就得到了一个 \(\mathcal O(n^2m^2)\) 的暴力 bfs 的做法。

观察一下这个求最小值的性质,以及染色的性质,可以用图论关系来刻画:考虑刻画如下的传递关系:\(u\) 被染色导致最终 \(v\) 被染色,此时连边 \(u\to v\)。然后求出 \(u\) 可达的点数即可。但是你显然不能直接建出来这张图。你需要求的是缩点成 dag 后,大小最小的无出度 SCC 的大小和数量。那么考虑 SCC 合并的过程,如果 \(u\Rightarrow v\)\(v\Rightarrow u\),那么 \(u,v\) 事实上是等价的;如果 \(u\Rightarrow v\)\(v\not\Rightarrow u\), 因为我们希望到达尽量少的点,那么 \(u\) 就是没有用的。

这启发我们动态维护当前有希望成为最终统计对象的 SCC。我们可以考虑动态维护这些 SCC,如果存在出度但是无法合并了就立刻标记为无用。然后考虑一起维护这些 SCC。

然而你维护 SCC 是不好做的,考虑对于一个集合 \(S\),什么是重要的。我们可以用这样的判定:任意一个点 \(u\in S\),使得对于任意 \(v\) 都有 \(u\Rightarrow v\)\(v\Rightarrow u\)。并且这条判定,只要对于任意一个 \(u\) 满足,那么一定所有 \(u\) 都是满足的。

我们只需要找出一个关键点 \(u\in S\),然后 \(S\) 是一个 SCC 的必要条件是任意 \(v\in S,v\Rightarrow u\),这启发我们只维护单向的可达关系,得知了这些之后,只需要从关键点开始找哪些 \(v\in S\) 使得 \(u\Rightarrow v\)。记录有 \(cnt\) 个,那么找出最终所有这些互相两两不可合并的 \(S\) 之后,最小值就是 \(\min(cnt_S)\),统计最小值个数也是容易的,就是第一问答案乘上多少个 \(S\) 可以达成它。

问题在于如何求出这些 \(S\)。初始状态就是有 \(n\) 个集合,每个集合的 \(S=\lbrace i\rbrace\)。考虑二集合 \(A,B\) 合并:要求 \(A\) 的代表元可以到达 \(B\) 的代表元,此时可以将 \(A\) 的所有元素加入 \(B\)

然后很神的一步,可以直接模仿 boruvka 算法:对于 \(A\),在 bfs 过程中只需要找到一个未合并过的集合 \(B\)。如果无法找到,说明其代表元所在的 SCC 是无出度的,可以直接在后续的合并过程中忽视该集合。

由于每轮有效集合个数减半。跑 \(\mathcal O(\log(nm))\) 轮就可以保证不会再出现合并了。每轮的 bfs 复杂度是线性的,因此时间复杂度 \(\mathcal O(nm\log nm)\)

P8519 是基本类似的。

NOIWC2022 T2

莫队可以动态维护前驱后继做到 \(\mathcal O(n\sqrt m\log n)\)。考虑一下复杂度瓶颈:是插入时,需要用平衡树查找前驱后继,并更新 \(pre,nxt\);但是删除时 \(pre,nxt\) 都是已知的,在不考虑平衡树操作时它就是 \(\mathcal O(1)\) 的,这启发我们设计仅删除的算法。考虑离线询问,固定左端点 \(l\) 所在的块扫描线 \(r\),维护当前的信息。具体而言,记离线下来左端点的块是 \([L,R]\),那么考虑从信息 \(U=[L,n]\) 开始做。按照这些询问的 \(r\) 倒序扫描线,动态维护 \(S=[L,p]\) 的信息。删除可以做到 \(\mathcal O(1)\),撤销删除可以使用栈记录,也可以 \(\mathcal O(1)\),对于 \(U\),应该从上一次得到的 \(U'\) 删去左边的前缀得到。对于真实询问的 \([Q_l,Q_r]\),应该从 \(S\) 删去一段前缀。这段前缀是可以暴力删的,这是因为移动距离 \(\leq\sqrt n\)。这样,删除插入(撤销删除)的复杂度都可以做到 \(\mathcal O(1)\),各自是根号次操作。那么总复杂度 \(\mathcal O(n\sqrt m)\)

猫树分治也是可以做的!运用拆贡献的思想,我们考虑计算单侧每一个数对每个询问的贡献系数。考虑一个特殊的序列:\(\lbrace1,3,5,7,2,4,6,8\rbrace\),我们在分治取 \(mid=4\),然后发现每一对都满足右边是一个,左边是另一个。然后考虑权值函数 \(w(x,y)=|x-y|\)\(x\in R,y\in L\) 的计算是平凡的:直接拆掉绝对值。这启发我们,对左右侧分别排序,维护单侧相邻的贡献。考虑在单侧排序后相邻的一对 \((i,j)\) 在对侧的一段区间是存在 \(|i-j|\) 贡献的,否则你可以把绝对值拆了,拆到这两个数上就是 \((i+j)\) 的贡献。然后直接扫描线维护一下单侧相邻的贡献,这对于右侧是一段后缀,那么二维数点就是 \(\mathcal O(n\log^2n)\) 了。注意到倒序扫描线可以是合并的关系,对于分治区间的排序可以归并减小常数。

P9258

考虑模仿本质不同子序列的计数方法,我们要求对于子序列 \(p_i\) 而言,对于任意 \(i\),不存在任意 \(j\in(p_i,p_{i+1})\) 使得 \(a_{j}=a_{p_i}\)。(设 \(p_{k+1}=n+1\))。模仿一下,我们要求左括号往上一个选的位置都是右括号,对称同理。然后用和的方法描述,左括号视为 \(1\),右括号视为 \(-1\)。那么要求任意后缀和 \(\leq 0\),任意前缀和 \(\ge 0\),总和为 \(0\)。对于两个串分开 dp 一下就行了。时间复杂度 \(\mathcal O(n^3)\)

P7013

首先考虑二分答案 \(mid\),判定是否可行。将所有区间按照 \(l\) 进行排序。那么考虑已经填好了 \(t\) 个区间,则当前在放标号为 \(p\) 的时候,就要求这 \(t\) 个中最早与其相交的是第 \(k\) 个,那么该区间标号必然 \(\leq k+d\),可以求出第 \(i\) 个区间的标号值上限 \(lim_i\)。显然我们要求对于任意 \(t\) 有最多 \(t\)\(lim\leq t\)。等价于 \(lim_i\ge i\),这是因为 \(l\) 有序因此 \(lim\) 有序。接下来考虑构造方案。每次你找出最小的 \(t\) 使得恰好有 \(t\)\(lim_i\leq t\),对于这些可以放的,贪心的根据直觉放这些中最小的 \(r\) 的即可,这样对后续的 \(lim\) 影响较小。线段树优化寻找 \(t\) 以及构造的过程,时间复杂度 \(\mathcal O(n\log^2n)\)

QOJ5097

首先考虑 \(\prod(\sum x_i)\) 可以使用乘法分配律。对于每一个组选取一个代表元相乘算贡献,那么我们可以对于所有选数的方案算有多少种分组方式会让它出现。那么对于一个选 \(k\) 个数出来的方案而言,分组的方式都是一样的,我们需要对于所有 \(k=1,2,\cdots,n\) 求出所有 \(f(k)\) 表示分组的方案数。

对于 \(m=1\) 是每个组没有限制,有 \(f(k)=k^{nm-k}\),然后对于具体的系数可以背包 dp 做到 \(\mathcal O(n^2m)\)。考虑拓展到 \(m\) 任意,就是有 \(k\) 个不同的盒子,以及 \(nm-k\) 个不同的球,要求放入盒子中最终满足每个盒子大小模 \(m\)\(m-1\)。考虑更改一下求 \(f(k)\) 的形式。你可以先对所有 \(nm\) 分成 \(k\) 个非空组,然后对于每组的首个球让其不参与标号。这样就可以 dp,前 \(i\) 个数已经形成了 \(j\) 个组的方案数 \(f_{i,j}\),然后考虑是否新生成一个组。这样其实还不是很好做,你考虑在一次操作直接完成一个盒的方案。那么就是前 \(im\) 个数形成了 \(j\) 个组的贡献。因为实际上是多重集组合数的贡献来划分,所以你需要记录的是 \(\sum\prod\frac{1}{siz!}\)。转移是显然的,而 \(f(k)=(nm-k)!f_{nm,k}\)。这个复杂度就是 \(\mathcal O(n^3)\)。考虑优化这个过程,可以对新划分的盒子大小进行根号分治。处理小的以及处理大的分别处理然后合并,复杂度 \(\mathcal O(n^2\sqrt n+n^2m)\)

P7126

代表元思想,是构造有限信息这一思想的重要体现。

考虑对于连通块找代表元进行计数。令树上任意一个点定为根,对于一个 \(k\) 连通块定义其代表元为,\(dep\) 最小的点。如果有多个 \(dep\) 最小的点选定标号最小的点作为代表元,那么我们只需要求代表元的个数。考虑这样做为什么是对的:一个连通块有且仅有一个代表元;一个非代表元指向唯一的代表元点,也即可以确定唯一的等价类。那么应该说明后者的正确性。对于 \(u\) 可能指向的两个更浅的点 \(a,b\),我们希望说明 \(a,b\) 属于同一等价类。考虑 \(u,a\)\(\text{lca}\)\(a'\)\(u,b\)\(\text{lca}\)\(b'\),不妨设 \(dep_{a'}\ge dep_{b'}\)。令 \(\text{dis}(a',u)=a_1,\text{dis}(a',a)=a_2,\text{dis}(b',u)=b_1,\text{dis}(b',b)=b_2\)。由我们的定义,应该满足 \(a_2\leq a_1,b_2\leq b_1\)。如果 \(a'=b'\) 是容易证明 \(a,b\) 属同一等价类的;否则考虑 \(\text{dis}(a,b)=b_2+a_2+(b_1-a_1)\)。而 \(b_2+b_1\leq k,a_2-a_1\leq 0\),因此 \(\text{dis}(a,b)\leq k\),即 \(a,b\) 属于同一等价类。正确性得证。

那么考虑,一个点在什么情况下可以成为代表元:考虑这个点 \(u\)\(k\) 级邻域之中,如果存在标号 \(\in[l,r]\) 的点 \(v\)\(dep_v<dep_u\),那么 \(u\) 就是没用的;否则如果有 \(dep_v=dep_u\),就要求 \(v>u\)。也就是说对于标号 \(\in[l,u]\) 的点视为关键点后,要求 \(k\) 级邻域中的关键点 \(v\) 都有 \(dep_v>dep_u\);对于 \([u,r]\) 而言,将标号 \(\in[u,r]\) 的点视为关键点后,要求 \(k\) 级邻域的关键点 \(v\) 均有 \(dep_v\geq dep_u\)。显然 \(l,r\) 是独立的,我们只需要对于每个 \(u\) 找出最大的 \(r\) 使得 \([u,r]\) 会让 \(u\) 成为关键点,同理找出最小的 \(l\)。有了这些之后就相当于矩形覆盖,单点查询。可以离线询问后进行扫描线,树状数组维护二维数点。

问题在于,对于每个 \(u\) 求出这样的 \(l\) 以及 \(r\)。以求 \(l\) 为例,只需要找出 \(u\)\(k\) 级邻域中 \(dep_v\leq dep_u\) 的标号最大的 \(v\)。可以直接点分治,每一层维护线段树,离线子树内的所有点后,每次对于一段前缀进行数据结构上二分。由于是取最优化,所以甚至不需要不同子树的限制。时间复杂度 \(\mathcal O(n\log^2n+m\log n)\)

CF1967E1

考虑判定 \(a\) 是否合法:可以贪心构造 \(b\),注意到要求 \(b\) 非负,那么考虑取到该位置可以取到的最大值。即若 \(b_{i-1}+1\neq a_i\)\(b_i=b_{i-1}+1\),否则 \(b_i=b_{i-1}-1\),这一步要求 \(b_i\ge 0\),做不到就寄了。因此有一个暴力 dp:\(f_{i,j}\) 表示前 \(i\) 个位置,\(b_i=j\)\(a\) 的方案数。转移形如 \(f_{i,j}=[j+1<m]f_{i-1,j+1}+(m-1)f_{i-1,j-1},mf_{i-1,m}\to f_{i,m}\)。这样得到了一个 \(\mathcal O(nm)\) 的做法。然后考虑转移的形式很统一,可以考虑一些神秘格路计数优化。注意到奇偶性是确定的,然后旋转 \(45\) 度之后形如不允许触碰 \(y=0\),且首次到达 \(y=m\) 时结束。可以枚举最终结束位置然后做双直线间计数方案数。时间复杂度 \(\mathcal O(n^2/m)\)。平衡一下得到 \(\mathcal O(n\sqrt n)\) 的时间复杂度。

CF2042E

显然要从大往小贪心,那么相当于 \(2n\) 个点,多次查询删掉点 \(x\) 后是否存在一个连通块包含全部颜色,然后决定该点是否永久删去。然后考虑维护极大的合法连通块点集 \(S\),在删点过程中显然唯一确定。若 \(x\notin S\),可以直接删,否则考虑 \(x\in S\) 的贡献。那么新的 \(S'\) 也是唯一确定的:考虑与 \(x\) 相接的唯一大小 \(\ge n\) 的连通块。只需要判定 \(S'\) 的颜色数量是否 \(=n\)

将树定根为 \(1\),我们可以维护每个连通块的 \(top\) 表示子连通块的根,可以通过一些简单的讨论来维护当前子连通块的大小。那么考虑一个关键信息:\(S'\) 内有多少颜色是唯一出现的。那么考虑颜色的一对出现位置 \(x\to y\),只要路径上有点被删,那么 \(x,y\) 只能被保留一个。注意到你事实上可以暴力删除,可以维护 dfs 序上的树状数组来支持查询子树内唯一出现颜色个数。然后对于 \(top\) 来一个子树查询就好了。删除时设置为 \(0\)。时间复杂度 \(\mathcal O(n\log n)\)

CF1973F

考虑 \(d(n)_{\max}\) 对于 \(n\leq 10^8\)\(D=768\)。因此结论是,可能的 \(\gcd(a)+\gcd(b)\) 的种类数很少。然后你只需要对所有 \(x=\gcd(a),y=\gcd(b)\) 的所有 \((x,y)\) 处理出最小代价。最多是 \(d(a_1)d(b_1)\) 对,暴力处理是对的。如果有所有的 \(cost_{x,y}\),对于查询可以将这些排序后进行二分,做到 \(\mathcal O(q\log m)\) 的复杂度。问题来到处理 \(cost_{x,y}\)。有一个很显然的暴力,如果 \(x|a_i,y|b_i\) 该位置没有代价;如果 \(x|b_i,y|a_i\) 且不满足前者会有 \(c_i\) 的代价;如果都不满足该方案不合法,即 \(cost_{x,y}=+\infty\)。你这样做不会让 \(value\) 变大,且答案取 \(\max\),那显然是对的。

问题来到快速处理 \(cost_{x,y}\)。先固定 \(a_1,b_1\) 然后枚举 \(x|a_1,y|b_1\) 再考虑。后续还需要 swap 一下两者计算。考虑一个弱化版本 \(x_1|x,y_1|y\)\(\Delta cost\) 是什么。此处设 \(cost_{x,y}\) 存在,那么 \(cost_{x_1,y_1}\) 也是存在的。那么考虑就是所有,\(x_1|a_i,y_1|b_i\) 但是 \(x|b_i,y|a_i\) 的位置的 \(c_i\) 之和。 那么可以由 \(cost_{x_1,y_1}\) 加上这些变化量。那么考虑一下高维前缀和的思想,令 \(k=\omega(n)_{\max}\) 对于 \(n\leq 10^8\)\(8\)。那么考虑对这 \(2k\) 个维度执行一下高维前缀和。那么只需要找出这些 \(\Delta\) 的位置。为了方便处理 \(cost\),我们同时维护一个 \(cnt\) 表示合法的位置数,那么 \(cost_{x,y}\) 存在当且仅当 \(cnt_{x,y}=n\)

对于每个位置,我们可以使用容斥的思想。对于 \(x|a,y|b\) 以及 \(x|b,y|a\) 各自做贡献,然后容斥一下 \(xy|a_1,xy|b_1\) 的信息。对于一个 \(p|a_i,q|b_i\)\(p|a_1,q|b_1\) 的打 tag,直接在两者各自的 \(\gcd\) 位置打 tag 就全对了。然后高维前缀和还原。时间复杂度 \(\mathcal O(n\log A+4^{\omega (A)}+q\log A)\)

LOJ3560

  • 复杂度分析,拆点,定义域值域互换,最短路形优化 dp 转移。

显然你可以估计答案的上界,然后有一个 \(p(u,t)\in\lbrace0,1\rbrace\) 表示 \(t\) 时刻在 \(u\) 是否可行。定义 \(l_u\) 表示 \(u\) 所在的限制路径长度。考虑 \(u\) 是否在某个限制环上,对于 \(u\) 不在限制路径上的情况,\(p(u,t)=1\)\(t\) 不存在或者是一段后缀;在限制路径上的情况,对于 \(l\) 同余的 \(t\) 要么不存在 \(1\) 要么是一段后缀。那么可以定义域值域互换,设计 \(f_{u,i}\) 表示到达 \(u\) 时刻模 \(l\)\(i\) 的最小时刻,如果不在限制路径上 \(l=+\infty\)。考虑一下 \(f_{u,s}\to f_{v,t}\) 的转移,要求 \(u=v\) 或者 \((u,v)\in E\),且 \(t\) 时刻没有怪兽在 \(v\),且 \(t\) 时刻没有 \(v\to u\) 的怪兽。那么就是,\(\min_{k\in \N}(f_{u,s}+kl_u+1)\) 使得 \(f_{u,s}+kl_u+1\equiv t(\bmod l_v)\)。如果 \(u,v\) 同环就要求,不允许 \(t-1\) 时刻是 \(v\)\(t\) 时刻是 \(u\)。令 \(L=\sum ℓ_i\),直接做的复杂度会高达 \(\mathcal O(L^4+mL)\),这是计算转移的数目得出的。具体使用 dijkstra 来转移。我们的目标是减少无效转移数量。只保留有效的转移。

对转移具体分类讨论:

  • \(u,v\) 均不在限制环上:可以直接 dijkstra 转移,这样的 \((u,v)\) 只用转移一次;事实上同理的,\(v\) 不在限制环但 \(u\) 在限制环是相同的。该类转移总复杂度 \(\mathcal O(m)\)
  • \(u\) 不在限制环但 \(v\) 在限制环的情况:我们希望减少无效的转移。注意到对于 \(u\) 等待 \(t_1+t_2\) 时刻到 \(v\) 在某些情况下可以转化成 \(u\) 等待 \(t_1\) 时刻再到 \(v\) 等待 \(t_2\) 时刻。那么我们希望将大部分 \(u\to v\) 的转移转化成后者,那么考虑 \(k=(t_1+t_2)\) 无法被转化的情况,就是中间无法避开守卫的情况。找到最小的 \(nxt\) 表示在严格大于 \(f_u\) 之后第一个被守卫经过的时刻,那么我们可以只转移:\(t=f_u+1\) 以及 \(t=nxt+1\)。注意 \(f_u+1=nxt\) 时是无法执行前者的转移的。该类转移总复杂度 \(\mathcal O(m)\)

说明一下:如果一条边是理论最优的,可以从边的备选集合中删除。

  • \(u,v\) 均在限制环的情况,需要考虑 \(u,v\) 是否同环。如果 \(u,v\) 同环,注意特殊性质保证了只存在该类转移。分讨一下正序和逆序,用类似上一类的思想,对于 \(f_{u,s}\) 可以向 \(\mathcal O(1)\)\(f_{v,t}\) 进行转移。也就是说,在具体转移时只需要考虑 \(k=0\) 的情况。即最小时刻即为需要考虑的。该类转移总复杂度 \(\mathcal O(L^2)\)
  • 重点在于 \(u,v\) 均在限制环并且 \(u,v\) 不同环的情况。我们想要干的事情是:对于两个相邻的不同环 \(a,b\),将转移的次数控制在 \(\mathcal O(ℓ_aℓ_b)\)。类似的,我们考虑 \(nxt\) 表示在环 \(v\)\(f_{u,s}+1\) 的后继。与之不同的是,我们并不能毫无顾忌的在 \(u\) 上一直等待,否则可能会碰见怪兽。考虑在 \(nxt\) 时刻时环 \(u\) 的位置上并没有怪兽。那么你可以提前到 \(v\) 然后立刻到 \(u\) 进行一个折返,这样就可以转移到 \(v\) 更后面的状态。此时这个转移时理论最优的,因此可以删去;
  • 如果 \(nxt\) 时刻 \(u\) 有怪兽,那么尽管对于 \(nxt\) 之前的 \(f_{v,t}\) 可以执行转移,但是对于 \(nxt\) 及以后的状态而言,考虑找到 \(P\) 时刻表示 \(nxt\) 之后首个模 \(l_u\)\(s\) 的时刻,对于 \(P\) 类似的找像 \(nxt\) 一样的后继 \(Q\),判定 \(Q\) 时刻时 \(u\) 位置是否有怪兽,执行正常的转移。我们想要说明的是,转更多圈是没有意义的:这个情形是循环坠入的,转更多圈得到的情况与此相同。注意,此时边 \(u\to v\) 的转移不一定理论最优,因此不能从边的备选集合中删去。

考虑分析一下不同环间转移的复杂度:对于第一次找 \(nxt\)\(l_b\) 组可以消除到剩余最多 \((l_b/l_a)\) 条边,但是对于第二次虽然会造成 \((l_a-1)\) 个状态的访问,但是只会访问这么多。因此对于一个点向下一个考虑是 \(\leq 2l_b\) 个的。乘以 \(l_a\) 就是 \(\mathcal O(ℓ_aℓ_b)\) 的环间转移。求和可以得到 \(\mathcal O(m\log m+L^2)\) 的复杂度。

秒了的还要写吗

CF1667E 和 CF1610H 和 P9985 都过于简单了。

QOJ5205

先进行一步经典的转化:并不真正删除,如果抽到了已经选过的那就是没有影响的。我们希望考虑对 \(m\) 状压而不是对 \(n\) 状压。考虑一个基于人的集合的暴力做法:枚举一个集合的序列 \(U=\lbrace 1,2,\cdots,m\rbrace=S_1,S_2,\cdots,S_k\),满足对于 \(1\leq i<k\)\(S_{i+1}\subseteq S_i\)\(S_{i+1}\neq S_i\),这种集合序列出现的概率。然后考虑对于单步 \(S\to T,T\subseteq S,T\neq S\) 就要求 \(S\setminus T\) 之中的均为 \(0\)\(T\) 之中的均为 \(1\)。那么计数其有 \(cnt_i\) 种方案使得 \(S\to T\),有 \(num_i\) 种方案使得 \(S_i\) 变化。那么一组方案的权值就是 \(\prod\frac{cnt_i}{num_i}\)。考虑怎么求 \(num\):减去一下 \(S\) 中均为 \(1\) 或者 \(S\) 中均为 \(0\) 的即可,可以高维前缀和处理子集加。考虑怎么求 \(cnt(S,T)\)。令 \(A=S\setminus T\),那么要求对于合法的集合 \(B\)\(T\subseteq B\)\(A\cap B\) 为空集。后面的 dp 部分就是考虑 \(f_S\) 表示 \(S\) 为结尾的所有序列的权值乘积。暴力枚举 \(T\subseteq S\) 进行转移,\(cnt\) 可以递推处理。时间复杂度 \(\mathcal O(nm+3^m)\)。考虑优化:可以按照 \(\text{popcount}\) 进行转移。形如 \(\frac{f_S}{num_S}\times c_{T}\to f_{S\cap T}\)。其中 \(c_T\) 表示集合 \(T\) 的出现次数。考虑容斥即可,先计算子集和,然后再高维差分还原。至此复杂度优化为了 \(\mathcal O(nm+m^22^m)\)

CF1292F

考虑建图。定义边 \(u\to v\) 表示 \(ka_u=a_v\)。则这张图的性质是若 \(u\to v\)\(v\to w\)\(u\to w\)。每次对于 \(u\to a,u\to b\) 可以删除 \(a\)。显然对于弱连通块之间是相互独立的。有一个很显然的猜测:每次必然删除无出度的点,即当前序列不存在别的 \(a_j\) 使得 \(a_j=ka_i\)。证明,考虑使用调整法,如果删去了一个有出度的点,对指向它的边任意找一个来替换一定是可行的,且对后续操作是不劣的。考察一个非孤立点连通块的最终形态,一定是两个点的一条边,否则一定可以继续操作。那么对于一个连通块的删数最大值就是入度 \(>0\) 的点个数 \(-1\)

弱连通块间独立。注意到删除序列是困难的,考虑添加点的序列。那么每次要求选择一个有入度的点 \(u\),然后新加入的 \(v\) 连边 \(v\to u\),满足 \(a_u=ka_v\),注意这可能加入不止一条边。令值域 \(m=60\),那么注意到如果一个点 \(u\) 满足 \(a_u>m/2\),那么这个点一定不存在出度,是相对平凡的。然后考虑剩下的 \([1,m/2]\) 中的数,是比较复杂的,因此可以考虑状压。考虑状压的状态是什么,在加点过程中,维护每个点是否有出度,表示是否已经被激活。然而你显然不能对 \(m/2\) 都状压,继续缩状态。

然后是这样的,你可以直接钦定对于被加的点基于的那个点,是一个无入度的基础点。正确性是因为这个图的性质。那么可以直接找出所有基础点,基础点的数量是 \(1\sim m/2\) 的最长反链,一定 \(\leq m/4\)。这样状压的复杂度就是正确的,然后暴力加数即可,时间复杂度 \(\mathcal O(2^{m/4}n^2)\)

P9907

正难则反,考虑计算断开之后仍然连通的边的数量。重要性质:无向图的 dfs 生成树中不存在横叉边,也即全部为返祖边。那么考虑对于断开树边,可以做一做预处理做到 \(\mathcal O(1)\) 判定每条边是否合法(前后缀 \(low\)\(\min\) 以及暴力遍历子树 \(low\)\(\min\))。重点在于对非树边的合法性判定。

非树边是重点,不妨设 \(v\) 的深度更大,那么整棵树被剖分为了三个部分 \(A,B,C\),从上往下为 \(u\) 往上的到根链,由于不存在横叉边,那么子树向上连只能连到这个链上去;\(u\)\(v\) 不包含端点的非空链以及它挂着的子树;\(v\) 所有儿子的子树。

对于 \(u\) 挂着的非 \(v\) 方向的子树,处理子树内返祖边指向点深度 \(\min\) 也即 \(low\),维护一下前后缀的 \(\max\) 就可以判定 \(u\) 挂着的子树是否合法;对于 \(B\) 部分,记录 \(v\)\(dep_v-dep_u-1\) 级祖先为 \(u'\),那么 \(B\) 需要考虑的是 \(u'\) 子树扣除掉 \(v\) 子树。如果用 dfs 序来维护 \(low\)\(\min\) 就可以得知其是否与 \(A\) 连通。对于 \(B\) 的 dfs 序刻画是容易的。现在分为两种情况:\(A,B\) 连通与 \(A,B\) 不连通。

首先考虑 \(A,B\) 连通的情况,对于 \(v\) 的所有儿子 \(p\) 而言,\(p\) 子树只要与 \(A,B\) 其中一者连通即可。对于所有子树开一个 map 维护,一个子树在 \([1,dep_v)\) 中的的 \(low\) 是否有且只有一种;考虑 \(A,B\) 不连通的情况。那么需要有一个 \(p\)\(A,B\) 均连通,剩下每个 \(C\) 都需要与 \(A,B\) 其中一者连通。这相当于是在前者的基础上增添了限制。考虑其是否满足前者,然后处理每个 \(p\) 子树的 \(\min,\max\) 来判定是否每个子树均是,只与 \(A,B\) 中恰好一个部分连通。

自下往上处理,将所有返祖边在深度更大一端进行统计,启发式合并维护子树信息。可以做到 \(\mathcal O(n\log^2n+m\log n)\)

posted @   nullptr_qwq  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示