2024.11 做题记录
1. P4381 [IOI2008] Island
准确来说,这题是\(10\)月份做的。
题意转化一下,实际上就是对于每一个连通块,找到最长的路径长度。
答案就是所有连通块答案之和,所以以下我们只讨论一个连通块的情况。
如果是一棵树呢?发现实际上很好做,实际就是一个树形dp,处理出以每一个节点为起点,向其子树走的最大和次大路径长度,记为\(w_{u,1},w_{u,2}\),则答案为\(\max_{i=1}^{n}(w_{u,1}+w_{u,2})\)。
但是实际上本题是一道基环树,那么我们如果把那个环上所有边删去,则剩下的是一个森林,可以按上述方式处理。但是有可能最终答案所在路径可能会经过环上的边,所以我们还得处理出经过环上边的答案。
预处理出\(g_{u}\),其中\(u\)为环上结点,\(g_u=w_{u,0}\)。
如果我们从\(u\)进环,从\(v\)出环,则答案为\(dis(u,v)+g_u+g_v\)。怎么去处理呢?
首先先考虑如何遍历环上所有路径,枚举其终点,且钦定这条路径为起点到终点的顺时针走的路径,所以如果我们“转两圈”(枚举终点两轮)则可以处理出所有路径的答案。所以环上的点构成的序列需复制一遍放在该序列后面。
但是这里,我认为在转两圈时用线段树动态维护其前\(n-1\)个点的\(g_j+dis(j,i)\),每往后挪一个点就将其前面\(n-1\)个点都加上\(dis(i,i')\),然后答案就是其前\(n-1\)个点\(+g_{i'}\)的最大值。
时间复杂度\(O(n\log n)\)。
然而实际上可以预处理一个距离的前缀和数组\(f\),然后用单调队列维护出\(g_i-f_{i}\)的最大值再加上\(g_{i'}\)。
时间复杂度\(O(n)\)。
实现写的线段树那种,提交记录
2. P10933 创世纪
如果把每一个限制的关系用有向边建出来,发现是一个内向基环森林。
然后就相当于求一个树形dp,对于环外树,设\(dp_{u,0/1}\)为在以\(u\)为根的环外树子树内第\(u\)个点 不选/选 的最大选的点的个数。
则有\(dp_{u,0}=\sum_{v\in nxt_u}\max(dp_{v,0},dp_{v,1})\),\(dp_{u,1}=\sum_{v\in nxt_u}(dp_{v,0}+\sum_{k\in nxt_u且k\neq v}\max(dp_{k,0},dp_{k,1}))\)。
然后再对环上跑一遍类似dp,需要断环,并枚举环的起点是否取。
时间复杂度\(O(n)\)。
3. CF117E Tree or not Tree
如果设所有关闭的边权值为\(1\),否则为\(0\)。
则答案为\(max(1,基环树上边权之和)+非环边边权之和\)。
分开讨论,考虑将基环树的环缩点,然后对于上式的后面那项用树链剖分处理,然后对于环,开一个线段树单独处理。
然后对于修改\((u,v)\),先在树剖上改,再倍增跳到环上,根据题意分类讨论修改环上权值即可。
时间复杂度\(O(n+q\log^2 n)\)。
码量大,我写了4KB。
4. AT_abc284_g Only Once
首先可以推一推样例,发现这个问题有点类似一个东西:
- 如果我们把\(i\)连向\(a_i\),最后构成一个内向基环森林,然后贡献实际上就是路径上的非环节点个数。
所以我们考虑对\(1\)个节点计算方案,然后再乘上组合数从而获得答案。
以下称节点 \(a_i\)为\(i\)的后继点,即图上以\(i\)为起点的这条边的终点。
所以枚举该点到环的距离\(d\)(即从这个起点出发,路径上非环节点数,包括自己)。
-
考虑路径上的节点的方案,即\(\sum_{d=0}^{n-1}A_{n-1}^{d}\),为什么是\(n-1\)里选\(d\)个呢?因为选择的是该路径上每个点的后继点,有\(d\)个位置,\(n-1\)个数(除去起点)。
-
然后考虑环上节点,枚举环长\(s\),所以为\(\sum_{s=1}^{n-d}A_{n-d-1}^{s-1}\),因为从起点出发到达环上的第一个节点已经定下,所以从剩下\(n-d-1\)个点选出\(s-1\)个后继点。
-
然后还有一些点既不是环上点也不是路径上的点,他们的后继点就无所谓,即为\(n^{n-d-s}\)。
所以根据以上,我们可以得出一个式子:
但是起点可以有\(n\)个,所以方案数式子为:
但是这个式子直接求是\(O(n^2)\)的,所以要进行转化。
设\(f(d)=\sum_{s=1}^{n-d}A_{n-d-1}^{s-1} n^{n-d-s}\)。
则有
然后把\(s=1\)划出来,有:
但是又不太能递推,所以可以考虑再将和式里的\((n-d)\)划出来。
则有:
这样就可以递推了。
初始化\(f(n)=0\)。
然后我们只求出了方案数,但是实际上要求出权值总和,所以最终答案为
然后组合数那块如果用预处理阶乘及其逆元的方式不行,因为\(M\)不是质数。所以考虑递推,\(A_{n-1}^{i}=A_{n-1}^{i-1}\times (n-1-i+1)=A_{n-1}^{i-1}\times (n-i)\)。
时间复杂度\(O(n)\)。
代码短,但是思维难度大,推式子也挺难的。
5 \(\sim\) 13
14. CF1912H Hypercatapult Commute
可以发现,如果我们把每一个城市往另一个城市的运输方向用有向边建出来,则原图一定是一个内向基环树。
所以移动方案是将所有环外树的居民先从下往上转移到环上。然后在环上某一个点开始,依次按照环的顺序转移。如果以环上其中一个点为起点开始转移,最后能使所有人到目的地则合法。
首先发现,我们其实是可以把所有环外树的节点按这棵环外树的拓扑序(即从上往下)将其放入环内该环外树根的前面。这样实际上与原图是等价的。
所以现在考虑如何构造一个环使得存在一个点,从这个起点出发能满足所有要求。
现在考虑起点的特殊性,会发现从起点出发的所有人与目的地为起点的所有人都一定能满足要求。而把这些人抛开后,剩下的入必须构成一个DAG。
于是——破案了。这里思路是,将每个人的起点与终点连边,然后对于每一个连通块,如果本来就是一个DAG,则答案加上 \(该连通块的点数-1\) ,否则判断是否存在一个点,使得删去改点及其连边后该连通块变为一个DAG,则答案加上 \(该连通块的点数\),如果不存在这样的点则无解。
时间复杂度 \(O(nm)\)。
15. CF1903F Babysitting
可以发现每一个点都有两种状态:选或不选。这就启发我们,可不可以用2-SAT来解决这个问题。
设 \(i\)为选第 \(i\) 个点, \(i+n\) 为不选第 \(i\) 个点。
最小点覆盖就是一个点集使得任意一条边的两个端点中至少有一个在点集内。那么对应如果不选 \(u\) 则必选 \(v\),反之亦然。则有边 \((u+n,v)\),\((v+n,u)\) 。
然后想要最小值最大,则考虑二分答案。
设当前值为 \(mid\),那么如果选了 \(u\),则 \([u-mid+1,u+mid-1]\) 的点都不能选,则有边 \((u,x)\) ,\(x\in[u-mid+1,u+mid-1]\)。
但是会发现这是区间连边啊,直接连可能会到 \(n^2\) 级别的啊,怎么开的下?
向区间连边,可以想到线段树优化建图。所以建一棵线段树,然后每个点向其两个儿子连有向边。然后进行区间连边。
所以就出来了,二分答案 \(mid\),每一次重新建边并跑Tarjan进行判断是否有解就行了,找到最大的 \(mid\) 使得有解。
时间复杂度 \(O(n\log^2 n)\)。
16. CF1970E Trails
首先Easy版就不说了。
然后是Medium版。设 \(c_i=s_i+l_i\)。根据题意,设矩阵 \(f\) ,\(f_{i,j}=c_i\times c_j-l_i\times l_j\) 。
所以答案为 \(\sum_{i=1}^{m} (f^n)_{1,i}\)。
时间复杂度 \(O(m^3\log n)\)。
然后就是Hard版。发现 \(m\le 10^5\),连矩阵都开不下了?这怎么做?
发现刚才那个 \(f\) 矩阵可以拆成两个矩阵相乘:
设 \(A=\begin{bmatrix}c_1 \ \ l_1\\c_2 \ \ l_2\\ .\\.\\.\\c_m \ \ l_m\end{bmatrix},B=\begin{bmatrix}c_1\ \ \ \ \ c_2\ \ \ \ \ c_3\ \ \ \ \ ... \ \ \ \ \ c_m\\ -l_1\ \ -l_2\ \ -l_3\ \ ... \ \ -l_m\end{bmatrix}\)。
则答案为 \((AB)^n\),而 \(AB\) 为一个 \(m\times m\) 的矩阵,太大了。但是矩阵有结合律,则有 \((AB)^n=A\times (BA)^{n-1}\times B\),而 \(BA\) 仅为一个 \(2\times 2\) 的矩阵,可以进行矩阵快速幂,最后再与 \(A\)、\(B\) 相乘。
但是乘完 \(A\) 后如果又乘 \(B\) ,这个矩阵为 \(m\times m\)的,又会炸,但是我们只求第一行,所以只用算第一行的值。
则总时间复杂度为 \(O(m+\log n)\) 。
17. CF2030E MEXimize the Score
很难阿。
首先考虑如果对于一个序列,它的最大值为多少。
会发现一个数 \(w\) 最多可以使答案 \(+1\),就将其放在那个只有 \([1,w-1]\) 的划分里,会使答案 \(+1\) 。
所以设 \(cnt_i\) 为 \(i\) 在序列里的出现次数,则答案为 \(\sum_{i=0}^{n}(\min_{j=0}^{i}cnt_j)\)。
所以就此为突破口,我们需要求出所有子序列的上述值。
考虑每个单一元素对答案的贡献,所以枚举元素 \(i\) 和 \(\min_{j=0}^{i}cnt_j\),对于 \(>i\) 的数取多少个与取哪些无所谓,所以为 \(\Pi_{j=i+1}^{n} 2^{cnt_j}\) 。然后对于 \(\le i\) 的数,这个值不太好求,所以考虑用 dp 来求这个值。
设 \(dp_{i,j}\) 为 \(\min_{k=0}^{i}cnt_k = j\) 的方案数。
对于每一个 \(i\) ,枚举 \(j\)。分类讨论:
- 如果填入 \(j\) 改变了最小值,则有 \(dp_{i,j}=C_{cnt_i}^{j}\times \sum_{k=j+1}^{n} dp_{i-1,,k}\) 。这里的 \(\sum\) 值用前缀和优化此处可以做到 \(O(n)\)。
- 如果填入 \(j\) 未改变最小值,则有 \(dp_{i,k}=C_{cnt_i}^{j}\times dp_{i-1,k},k\in[0,j]\) 。那么这里如果用填表法,则有 \(dp_{i,k}=dp_{i-1,k}\times \sum_{j=k}^{n} C_{cnt_i}^{j}\),后面那坨用前缀和优化,同样可以做到 \(O(n)\) 。
所以最终答案为 \(\sum_{i=0}^{n}(\Pi_{j=i+1}^{n} 2^{cnt_j}\times (\sum_{j=1}^{cnt_i}j\times dp_{i,j}))\)。
时间复杂度 \(O(n)\)。

浙公网安备 33010602011771号