2022.4
四月了啊...
推一首歌吧 当时小椿沿海边跑的时候的 BGM,经典青梅竹马打不过天降妹子
反正在家网课,就顺便停课了
改的都是简单题,难题都弃了
好菜啊
好像没有那种花一下午时间研究一个算法的耐心了
ε-(´∀`; )
4.1
T1
不算太难,不写了
T2
给你一个 \(n\) 个点的无向图,计数满足 \(K\) 个限制的生成树数量,每个限制是一个点集 \(S_i\),要求 \(S_i\) 在生成树上的导出子图联通。
\(n\leq 500,K\leq 2000\)。
生成树计数肯定是矩阵树定理。
考虑每一个限制 \(S_i\),\(S_i\) 的导出子图的边数 \(cnt_i\leq |S_i|-1\),且该限制被满足当且仅当取到等号。
我们考虑给原图每条边 \((i,j)\) 赋上边权 \(w(i,j)\),\(w(i,j)\) 为同时包含 \(i\) 和 \(j\) 的限制个数,我们发现这样,对于它的生成树 \(T\),边权和 \(w(T)=\sum cnt_i\leq\sum(|S_i|-1)\),等号取到当且仅当所有限制都被满足,所以满足条件的生成树就是最大生成树。
最大生成树就是经典做法了,忘了的话去看一眼 Luogu P4208 [JSOI2008]最小生成树计数。
还有 \(w(i,j)\) 的计算用 bitset 优化一下就是 \(O(\dfrac{n^2K}{\omega})\)。
总复杂度 \(O(n^3+\dfrac{n^2K}{\omega})\)。
T3
答案文件 10.1 K
长度为 \(n\) 的序列 \(a\),你有从中选出 \(k\) 个区间,区间的权值定义为所包含数的和。要求 \(k\) 个区间能覆盖整个序列,并且权值和最大,求最大权值和。
\(n\leq 10^5,k\leq \dfrac{n(n+1)}{2},|a_i|\leq5\times10^4\)。
首先是一些 key observation
若两个区间为包含关系,那么我们显然可以舍弃被包含的区间,然后选择当前未选择的区间中权值最大的。因为最多 \(n\) 个不包含的区间就可以覆盖整个序列,所以前 \(\max(0,k-n)\) 大的区间一定被选。
进一步观察,假设最优解选择了前 \(x\) 大的区间 \((\max(0,k-n)\leq x\leq k)\),此时剩下 \(m\) 个点没有被覆盖,那么剩下的 \(k-x\) 个区间一定两两不相交,并且每个区间至少覆盖 \(m\) 个未覆盖点中的一个。因为,若两个区间 \([l_1,r_1],[l_2,r_2]\) 相交,我们显然可以选 \([l_1,r_2]\) 代替,再选择当前未选择的区间中权值最大的,一定不劣。
所以我们先选上前 \(\max(0,k-n)\) 大的区间,计算它们的权值和以及它们覆盖的位置,然后再找到第 \(\max(0,k-n)+1\) 到第 \(k\) 大的区间。这个可以二分权值,然后再用树状数组,set 之类的东西求大于等于当前二分权值的区间个数,覆盖位置,权值和等等,这部分复杂度就是 \(O(n\log n\log V)\),但若干区间权值相同的情况真的是及其恶心。
然后我们逐个加入第 \(\max(0,k-n)+1\) 到第 \(k\) 大的区间,设当前未被覆盖的位置是 \(p_1,p_2,\dots,p_m\),我们需要对每个 \(1\leq i<m\) 求出 \(\max_{j=p_i}^{p_{i+1}-1}s_j-\min_{j=p_i}^{p_{i+1}-1}s_j\) (\(s\) 是 \(a\) 的前缀和),然后把这些值塞进 set 里,每次求出前 \(k-x-1\) 大的数的和,再加上 \(\max_{j=p_m}^ns_j-\min_{j=0}^{p_1-1}s_j\) 就相当于选出了 \(k-x\) 个区间覆盖了所有未覆盖点。随着 \(x\) 增大,会有一些 \(p_i\) 被删除,所以要动态维护那个 \(\max s_j-\min s_j\) 的值(插入,删除,查询前 \(k-x-1\) 大的数的和),搞一个 set 之类的数据结构就可以做了,这部分是 \(O(n\log n)\) 的。
据说还有 wqs 二分 + 线段树维护 DP 的做法,不太会...好像只有我写的题解做法还写了 10K
/tuu/tuu/tuu
4.2
T1
给你长度为 \(n\) 的字符串 \(S\) 和正整数 \(k\),判断 \(S\) 的每个前缀是否形如 \((AB)^KA\),\(A,B\) 可以为空串。
\(n\leq10^6\)。
没一眼切是不是应该去死
枚举 \(i\),判断 \(S[1 .. i]\) 是否能作为 \(AB\),所以只需求 \(\operatorname{lcp}(S[1 ..n],S[i+1 .. n])\)。
后缀数组,哈希都可以,新学了一下 Z 函数,这样就可以 \(O(n)\)。
周三没有模拟赛,复习一下字符串,写个字符串总结(flag
T2
这个是原题 CF1120D 加了一个求方案数,(其实上一题也是原题 CF526D)
所以就不写了
有 DP 做法,也有最小生成树做法(能不能求方案数?)(去看题解)
T3
ARC016D
这个二分很有意思的欸
题意很长不写了,总是是求期望,也容易列出状态转移方程
边界
但这个是有后效性的,不过后效性只与 \(f_{1,H}\) 有关,我们考虑钦定 \(f_{1,H}=A\),然后直接按方程转移,最后在看算出的实际 \(f_{1,H}\) 是否等于 \(A\)。
我们把这样计算出来的 \(f_{1,H}\) 看成是 \(A\) 的函数 \(f(A)\),想一想就有 \(f^\prime(A)\leq1\),所以就有 \([f(A)-A]^\prime\leq 0\) 他是有单调性的,可以二分出 \(f(A)=A\) 的 \(A\),也就是答案。
至于这个 \(f^\prime(A)\leq 1\) 应该也可以感性证明,考虑按拓扑序归纳,考虑 \(A\) 减小了 \(\mathrm{d}A\),\(f_{n,\star}\) 不会变所以它的导数是 \(0\leq1\),\(f_{x,j}\) 如果从 \(A+H-j\) 转移来那么 \(\mathrm{d}f_{x,j}=\mathrm{d}A\),如果从 \(f_{y,\star}\) 转移来,那么 \(\mathrm{d}f_{x,j}=\mathrm{d}f_{y,\star}\leq \mathrm{d}A\) 也是成立的,所以就证明了恒有 \(\mathrm{d}f_{\star,\star}/\mathrm{d}A\leq1\)。
4.4
T1 水题,T2交互
T2
猜树题,你要猜一颗二叉搜索树(按编号),可以 query(x,l,r)
询问 \(x\) 的子树是否恰好包含 \([l,r]\) 的点,询问次数是 \(2n\)。
想到单调栈求笛卡尔树的做法,我们也考虑使用单调栈。
按标号顺序依次加点,栈中维护一条最右链,发现是可以一次询问出当前点是否在栈顶节点的右子树。
总之要想到单调栈。
T3
你要构造一个 \(n\) 个点的简单图,每个点的度数至少为 \(k\),且图中所有度数为 \(k\) 的点不能相邻,最小化边数。
\(2\leq k\leq10,2k+1\leq n\leq 1000\)。
并不是构造题,因为重点在于求最小边数。
我们把点按度数等于 \(k\) 和大于 \(k\) 分类,设等于 \(k\) 的集合大小为 \(x\),那么两部分之间有 \(kx\) 条边,等于 \(k\) 的点之间不能连边,大于 \(k\) 的点之间可以连边,设连了 \(y\) 条。
容易列出不等式 \(kx+2y\geq(n-x)(k+1)\),为了 \(y\) 最小,解出 \(y=\min\left\{\left\lceil\frac{1}{2}[(k+1)n-(2k+1)x]\right\rceil,0\right\}\)。那么总边数 \(kx+y\) 就等于 \(\min\left\{\left\lceil\frac{1}{2}[(k+1)n-x]\right\rceil,kx\right\}\),\(x\) 为 \(\lfloor\frac{(k+1)n}{2k+1}\rfloor\) 或 \(\lceil\frac{(k+1)n}{2k+1}\rceil\) 时取得最小值。
得到了 \(x,y\) 之后构造方案就很简单了。
4.5
T1
给你一棵树,然后三个操作:
- 向集合中加入一个数
- 删除集合中的一个数
- 询问集合中 \([l,r]\) 的数编号的节点到 \(x\) 的最小距离
\(n\leq 10^5\),强制在线。
很显然的点分树,对每个点用线段树维护它点分树上的后代即可。复杂度 \(O(n\log^2n)\)。
T2
the same as 4.2 T3
T3
经过一个经典的卡特兰数模型 \((f_i=\sum_{j=0}^{i-1}f_jf_{i-j-1})\),问题转化成了求 \(\max_{i=l}^rv_7[(2i)!/(i!i!)]\),其中 \(v_p[x]\) 表示 \(x\) 的质因数分解中 \(p\) 的次数。
\(l,r\leq10^{10^4}\)。
首先有
进一步考虑什么时候才是奇数,我们发现当且仅当对于一个 \(i\),存在 \(k\) 使得 \(n\in[k\times7^i-(7^i-1)/2,k\times7^i-1]\),所以我们把 \(l,r\) 转成 \(7\) 进制从高往低逐位考虑即可。
复杂度瓶颈是进制转化,所以是 \(O(\log^2r)\) 的。
好困,,所以写的好像很简略。
今天还行,三道题都是自己想的,不过赛时摸的有点多,就写了一道。
这几天题也不太难,天天都是一车 AK,不过跟我垫底关系不大。
4.7
T1
抽象出题意就是,给你一个长 \(n\) 的 01 序列,你可以进行 \(m\) 次操作,每次选择一个长 \(l\) 的区间全部赋成 \(0\),求操作后最少剩下几个 \(1\)。
\(n,m,l\leq 10^6\)。
不要想贪心了,不要想贪心了,不要想贪心了,虽然看上去很对但它就是错的。
先考虑一个看上去没什么前途的 dp,\(f_{i,j}\) 表示前 \(i\) 个数,进行了 \(j\) 次操作,最少的剩下 \(1\) 的个数。
转移很简单:\(f_{i,j}=\min\{f_{i-1,j}+[a_i=1],f_{i-l,j-1}\}\),时间复杂度 \(O(n^2)\)。
关于这种有限制次数的问题,如果不限制次数,很容易求解最优方案,就要想到 wqs 二分。
答案的凸性容易证明,所以通过 wqs 二分就做到了 \(O(n\log n)\)。
T2
给你一个平面图,每次操作修改边权,你需要回答每次修改后的最小生成树,强制在线。
\(n,q\leq 10^5\)。
首先肯定想到 LCT,如果是边权只能变小就非常容易了,但我们无法在一条树边变大后快速判断它还在不在生成树上。如果可以离线,可以通过线段树分治等做到 \(O(n\log^2 n)\),但即使这样,巨大的常数也是很难通过的。
考虑本题的特殊条件,实际上,平面图的最小生成树有下面的结论:
这真是太妙了,看完题解激动了好长时间。
平面图的最小生成树的补集是其对偶图的最大生成树。
证明是容易的,把边集分成两部分后,平面图和对偶图两者任一个不连通当且仅当另一个中存在环,所以当两者都联通且不存在环(也就是在平面图和对偶图中分别形成一颗树),边数加起来恰好是 \(V-1+F-1=E\)。
对于本题,我们用两个 LCT 分别维护原图和对偶图的最小生成树和最大生成树,改变一个边权时,如果是变小,用原图的 LCT 判断生成树是否改变,如果变大,用对偶图的 LCT 判断。
时间复杂度 \(O(n\log n)\)。
T3
题意就是一个矩阵树定理,它的基尔霍夫矩阵(的 \(n-1\) 阶主子式)是长这样的(\(w\) 是给定的权值,\(S=\sum_{i=1}^{n-1} w_i\))
就是一个 \(n\times n\) 的矩阵,求 \(|K|\),不过 \(n\leq2^{20}\)。(但保证了 \(n\) 是 \(2\) 的次幂)
但这是一个循环矩阵,所以我们给它右乘一个范德蒙德矩阵(我数学菜,不知道怎么想到的,但乘完真的好神奇啊)
其中 \(\omega_n\) 是 \(n\) 次单位根。我们先令一个函数 \(f(x)=S+1-\sum_{i=1}^{n-1}w_ix^k\)。然后发现 \(KV\) 是长这样的
发现 \(KV\) 就是 \(V\) 在每列乘了 \(f(\omega_n^i)\),所以 \(|KV|=|V|\prod_{i=0}^{n-1}f(\omega_n^i)\),又因为 \(|KV|=|K||V|\),所以我们要求的 \(|K|\) 就等于 \(\prod_{i=0}^{n-1}f(\omega_n^i)\)。
直接 DFT 求出所有 \(f(\omega_n^i)\) 即可,复杂度 \(O(n\log n)\),好耶!
4.8
模拟赛直接摆烂,听完讲题 T2 直接弃
T1
给你长度为 \(n\) 的 01?
构成的串 \(|S|\)。
求 \(01\) 串序列 \(t_1,t_2,t_3,\dots,t_n\) 的个数,要求:
- \(|t_i|=i\)
- \(t_{i-1}\) 是 \(t_i\) 的子序列
- \(t_n\) 由 \(S\) 将每个
?
替换成0
或1
得到
模 \(998244353\),\(n\leq 250000\)。
先来牛逼的转化题意
先不考虑 ?
,从 \(t_n\) 到 \(t_1\) 就是把 \(S\) 每次删一个字符,不过如果两中删法得到的序列相同,那么算同一种方案,所以我们不妨钦定删 0
只能删连续一段 0
的最右面那个,删 1
只能删连续一段 1
的最左面那个,也就是说,相当于每次找到一个 01
然后删掉其中的 0
或 1
(再序列开头补一个 0
,结尾补一个 1
)。这样计数就不会重。
我们再每个两个位置中间加上分隔符,比如 101
变成 0A1B0C1D1
,每次选择其中⼀个 01
删除的时候, 我们也把分隔符删除。那么每个分割符被删除的时间就是一个 \(0\sim n\) 的排列,而 0
相当于它左面的分隔符先于右面被删,1
是右面先于左面。
把 0
换成 <
,1
换成 >
,计数满足条件的排列,据说这是一个经典问题。
\(f_i\) 表示考虑到第 \(i\) 个位置的方案,然后枚举前面 >
的位置容斥:
稍微变形:
现在它看起来就非常的卷积,于是分治 FFT 即可。
至于 ?
就是把序列分成若干段,每段分别计算,最后乘个组合数合并就行了。
时间复杂度 \(O(n\log^2n)\)。
T3
有一个 \(n\) 个节点的树,你要从中选出若干条长度为 \(k\) 的简单路径(两两边不能相交,点可以相交)。求最大权值和。
\(n\leq 2\times 10^5,k=3/4,-10^9\leq w_i\leq 10^9\)。
首先肯定往 DP 方面想吧,\(f_{x,j}\ (0\leq j<k)\) 表示节点 \(x\) 的子树中,并且从 \(x\) 往下选了一条长度为 \(j\) 的链,的最大权值。答案就是 \(f_{1,0}\)。
不过我们发现转移有些棘手,我们分别考虑 \(k=3\) 和 \(k=4\)。
\(k=3\) 时,如果 \(f_{x,j}\) 的 \(j=0\) 我们就是要把 \(y\in son(x)\) 的 \(f_{y,0}\) 和 \(f_{y,1}\) 两两配对,然后剩下的选 \(f_{y,2}\)(当然也可以不选),如果 \(j>0\) 就是选一个 \(y\) 从 \(f_{y,j-1}\) 转移上来,剩下同样这么配对。
配对的过程我们可以再搞个 DP,\(g_{i,j}\) 表示考虑到第 \(i\) 个儿子,当前选的 \(f_{y,0}\) 和 \(f_{y,2}\) 的差值为 \(j\)。记录一下前缀和后缀的 dp 值即可。
\(k=4\) 的情况类似,就是 \(f_{y,0}\) 和 \(f_{y,2}\) 配对,然后 \(f_{y,1}\) 之间也要两两配对,剩下的选 \(f_{y,3}\) 或不选。给 \(g\) 加一维 \(0/1\) 表示当先选的 \(f_{y,1}\) 的奇偶即可。
不过问题就是,这个 \(g\) 的 \(j\) 这一维大小是 \(|son(x)|\),这将导致总复杂度变成 \(O(n^2)\)。
但我们真的需要把这一维开到 \(|son(x)|\) 吗?
我们把 \(x\) 的所有儿子顺序随机打乱,我们发现最优转移的情况就相当于随机一个 \(+1\) 或 \(-1\) 的序列,最后的和为 \(0\),而这个随机 \(+1,-1\) 序列的前缀和最大值是低于 \(O(\sqrt n)\) 的。(这个好像有神仙证了),这意味着我们把 \(g\) 的 \(j\) 这维开到 \(O(\sqrt n)\) 算出正确答案的概率是及其大的。
于是,时间复杂度 \(O(n\sqrt n)\)。
4.9
T1 诈骗题,这不好。
T3 摆烂不看了,反正也没人过(好像数据锅了
T2
计数 \(n\) 个点的有向图,满足:
- 每个点的出度和入度都为 \(2\),且不存在重边
- 对每个点 \(u\),存在至多一个 \(p_u\),不能连边 \(u\rightarrow p_u\)。
\(n\leq 500\),模 \(998244353\)。
就大力容斥呗 /cy
题意抽象一下就是,\(n\) 对数填到 \(n\) 对位置上,其中每个位置有不能填的数,每对位置上的数不能相同,的方案数,不过因为每对位置两个数没有顺序,最终答案要除掉 \(2^n\)。
先容斥掉 \(p_u\) 不能填的限制,我们先求出一个系数 \(dp_{i,j}\) 表示序列中选出了 \(j\) 个位置填了对应的 \(p\),且有 \(j\) 个位置中有 \(k\) 个位置上的数只钦定了一次。记 \(cnt_{i}\) 表示 \(i\) 在序列 \(p\) 中出现的次数,容易得到 dp
然后,我们设 \(f(x,y,u,v)\) 表示 \(x\) 个单独的数,\(y\) 对数,放入 \(u\) 个单独位置,\(v\) 对位置的方案。那么最终答案就能写成
然后我们考虑求 \(f\),注意此时 \(f\) 中 \(x\) 个单独位置依然是有限制的,不能填对应的 \(p\),否则填的数就和原来和它一对的位置的数相同了。所以继续容斥
其中 \(g\) 和 \(f\) 含义类似,只不过单独位置上没有了限制。此时求 \(g\) 就容易很多了,若 \(u>0\) 考虑枚举其中一个单独位置放了哪个数,有以下递推
递推边界 \(u=0\),剩下的位置都是成对的,相邻两个位置不能填相同的数,与是继续……容斥。
然后我们就做完了,发现对于 \(f\) 和 \(g\) 都有 \(x+2y=u+2v\),所以状态数都是 \(O(n^3)\) 的,按照上面的式子挨个算,总复杂度 \(O(n^3)\)。
4.11
T1
新听说了一个东西,积和式,不过这个东西没法多项式时间求,好像不是很有用。
不过这个题给的矩阵是一个下海森堡阵,积和式和行列式一样是可以拉普拉斯展开的。所以不断按第一行展开,就容易得到 \(O(n^2)\) 递推求积和式和行列式的方法。
T2
\(W(n)=\sum\limits_{i=1}^k\varphi(p_1^{\alpha_1}\cdots p_{i-1}^{\alpha_{i-1}})\times p_i\times \sigma_1(p_{i+1}^{\alpha_{i+1}}\cdots p_{k}^{\alpha_{k}})\),其中 \(n=\sum\limits_{i=1}^kp_i^{\alpha_i}\) 是 \(n\) 的质因数分解。
求 \(\sum\limits_{i=1}^n W(i)\),\(n\leq 10^{10}\)。
首先这个数据范围看起来就非常 min25。
但是 \(W\) 不是积性函数欸!
再想想,我们有 \(W(p^{\alpha}\times n)=\varphi(p^{\alpha})\times W(n)+p\times \sigma_1(n)\)(\(n>1\) 且 \(n\) 中不包含质因子 \(p\))。
所以就魔改一下 min25 的第二步求 \(S\) 就能做了(要同时筛 \(W\) 和 \(\sigma_1\) 的和)
T3
有数列 \(f_0=f_1=1,f_n=9f_{n-1}+12f_{n-2}\),然后给你 \(n,P,a,b,c,d\),求 \(\gcd(af_n+bf_{n+1},cf_n+df_{n+1})\bmod P\),\(T\) 组数据。
\(T\leq 10^5,0\leq a,b,c,d\leq 1000,P\leq 10^9+7,n\leq 10^9\)。
首先记 \(g_n=\gcd(f_n,f_{n+1})\),找规律猜出结论,\(g_n=3^{\lfloor n/2\rfloor}\)。
然后通过辗转相除将 \(d\) 消成 \(0\),现在 \(ans=\gcd(a^\prime f_n+b^\prime f_{n+1},c^\prime f_{n})\)。
先求 \(G=\gcd(a^\prime f_n+b^\prime f_{n+1},f_n)=\gcd(b^\prime f_{n+1},f_n)=g_n\gcd(b^\prime,f_n/g_n)\)。为了求 \(\gcd(b^\prime,f_n/g_n)\),我们考虑求 \(f_n/g_n\) 在模 \(b^\prime\) 下的值,这个是容易矩阵快速幂做的。
现在 \(ans=G\times \gcd(\dfrac{a^\prime f_n+b^\prime f_{n+1}}{G},c^\prime)=G\times \gcd(\dfrac{a^\prime f_n/g_n+b^\prime f_{n+1}/g_n}{G/g_n},c^\prime)\)。提出来一个 \(g_n/G\) 变成 \(g_n\times \gcd(a^\prime f_n/g_n+b^\prime f_{n+1}/g_n,G/g_n\times c^\prime)\),跟上一步一样,计算 \(a^\prime f_n/g_n+b^\prime f_{n+1}/g_n\) 模 \(G/g_n\times c^\prime\) 的值即可。
最终复杂度就是 \(O(T\log n)\)。
4.12
T1
原
T2
维护一个集合 \(S\),支持一下两个操作:
-
插入一个数 \(w\)。
-
在 \([0,w]\) 中选择一个数 \(x\),\(S\) 中选择两个数 \(i,j\),最小化 \((i+x)\operatorname{xor} (j+x)\),求这个最小值。
\(n\leq5\times 10^5,w\leq 2^{40}\)。
首先是经典结论,如果有 \(a<b<c\) ,则有 \(\min(a \operatorname{xor} b,b \operatorname{xor} c)\le a \operatorname{xor} c\)。证明考虑 \(a\) 和 \(c\) 二进制下从高往低第一个不同的位即可。
所以我们发现,能作为答案的 \(i,j\) 一定是 \(S\) 中元素排序后相邻的数。然后我们再考虑什么样的 \(x\) 有可能作为答案,发现 \(x\) 作为答案的必要条件是:\(i+x\)(或 \(j+x\))是 \(i\)(或 \(j\))将二进制下为 \(0\) 的一位改成 \(1\),它后面全改成 \(0\) 得到的。这样的 \(x\) 只有 \(O(\log w)\) 个,于是能作为答案的 \(x,i,j\) 总共只有 \(O(n\log w)\) 对。
记 \(val_i\) 为 \(x=i\) 时的最小答案,我们用 set 维护所有可能作为答案的二元组 \((x,val_x)\),且 set 中只保留 \(x_1<x_2\) 且 \(val_{x1}>val_{x2}\) 的二元组(类似单调栈),这样就可以 \(O(\log n)\) 的在 set 中二分查询答案了。
复杂度 \(O(n\log n\log w)\)。
T3
码了 8.1 K 的数据结构题,调代码十分心情愉快(斯德哥尔摩了属于是)
一张无向图,最开始图仅有一个 \(0\) 号节点。现在有 \(n\) 次操作,每次操作为以下 \(5\) 种之一(不妨假设每次操作前这张图的节点编号区间为 \([l,r]\)):
-
删去 \(l\) 号节点,并删去 \(l\) 号节点连接的所有边。
-
删去 \(r\) 号节点,并删去 \(r\) 号节点连接的所有边。
-
增加 \(l-1\) 号节点,并连接 \(\min\{k-1,r-l+1\}\) 条边,第 \(i\) 条边连接 \((l-1,l-1+i)\),边有边权。
-
增加 \(r+1\) 号节点,并连接 \(\min\{k-1,r-l+1\}\) 条边,第 \(i\) 条边连接 \((r+1,l+1-i)\),边有边权。
-
对当前图询问最小生成树的边权和。
\(n\leq 5\times 10^5,2\leq k\leq10\)。
动态维护 MST 不是 LCT 吗,有删除?线段树分治好了,我会 \(O(nk\log^2 n)\) 暴力!很好,过了
正解的启发思路来源于一个部分分,前 \(k-1\) 次操作都是 \(4\),此后保证 \(l\leq 0,r\geq k-1\)。
我们假设现在已经得到了 \([l,r]\) 的最小生成树,要加入点 \(l-1\),此时我们尝试加入边 \((l-1,l-1+i)\),只需知道 \(l-1\) 到 \(l-1+i\) 路径上的最大值即可,也就是说,我们感兴趣的只是 \([l,l+k-1]\) 这些点两两路径上的最大值,于是我们把 \([l,l+k-1]\) 的点当做关键点,求出其在 \([l,r]\) 最小生成树上的虚树,虚树上的边权为其在原树上代表的路径的边权最大值,该虚树大小只有 \(O(k)\),但根据它我们完全可以求出加入 \(l-1\) 后的最小生成树!
于是我们得到了一下做法,左面加入一个点时,只维护此时 \([l,l+k-1]\cup[0,k-1]\) 在最小生成树上构成的虚树(加上 \([0,k-1]\) 是为了方便最后与右边的结果合并),考虑到有删除操作,把过程中得到的虚树全部用 \(O(nk)\) 的空间存下来即可。具体地,加入一个点以及其连接的 \(k-1\) 条边时,与原来的虚树上的所有边放到一起 kruskal 求出新的最小生成树,让后 dfs 求出新的虚树,这部分复杂度为 \(O(k\log k)\)。右边的同理,询问时,只需把 \([l,l+k-1]\cup[0,k-1]\) 的虚树和 \([0,k-1]\cup[r-k+1,r]\) 的虚树放到一起跑 kruskal 即可,这样总复杂 \(O(nk\log k)\),我们就做完了这个部分分。
再考虑正解,我们发现其与正解的差别就是正解需要考虑到当前 \([l,r]\) 长度可能小于 \(k\),且 \([l,r]\) 一直在变化不会一直包含 \([0,k-1]\),这个的解决方法却非常暴力,那就是定期重构。
设当前 \([L,R]\ (L-R+1=k)\) 为当前的中心区间,如果 \(r<R\) 或 \(l>L\),我们就直接令 \([L,R]\) 变成当前 \([l,r]\) 的中间位置,然后重新计算加入 \([l,L-1]\) 和 \([R+1,r]\) 点的那些虚树。下面分析复杂度。
考虑势能分析,定义势能 \(\phi=\max\{L-l,r-R\}\),插入操作回让 \(\phi+1\),而重构操作会令 \(\phi\) 减半,重构的复杂度为 \(O(\phi k\log k)\),那么总的复杂度不会超过 \(O(nk\log k)\)。
还有就是如果当前 \(r-l+1<k\) 我们就直接 prim 暴力求解即可,复杂度是 \(O(k^2)\),所以最终的复杂度为 \(O(nk^2)\)。不过实际的运行时间瓶颈显然不在这里,而在常数巨大的每次构建虚树。