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)\)。最终可以化简成:
调和级数处理一下 \(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)\)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】