2024.5.6 近期练习
P3354 [IOI2005] Riv 河流
如果我们设 \(f_{u,j}\) 表示子树 \(u\) 内放了 \(j\) 个伐木场的答案,发现很难转移。
我们多加状态,设 \(f_{u,i,j}\) 表示子树 \(u\) 放了 \(j\) 个伐木场,木材全部运到 \(i\) 去最小代价。\(i\) 是 \(j\) 祖先。
继续设 \(g_{u,i,j}\) 表示 \(u\) 建了伐木场,子树 \(u\) 放了 \(j\) 个伐木场,木材运到 \(i\) 去最小代价。
这是个背包的模型,合并儿子的答案即可。
事实上,\(v\) 转移到 \(u\) 的时候是用不到 \(g\) 的,我们用 \(g\) 把 \(f\) 更新即可,
P3565/P5904 [POI2014] HOT-Hotels(加强版)
简单版的话,我们可以先枚举两个点 \(u,v\) 出来。得到这两个点路径的中点 \(mid\)。
设 \(u,v\) 到 \(mid\) 的距离为 \(d\),那么我们要求的是到 \(mid\) 距离为 \(d\) 的点的个数(除去 \(u,v\))。
事实上,我们只需要计算 \(mid\) 为根,求距离为 \(d\) 的点的个数算贡献即可。
困难版我们无法这么算。为了避免算重,钦定一个根。设 \(f_{u,i}\) 表示 \(u\) 子树内距离 \(u\) 为 \(i\) 的点数,
\(g_{u,i}\) 表示 \(u\) 子树内还要一个距离 \(u\) 为 \(i\) 的点就可以形成三元组的二元组个数。转移显然。
计算答案有两种,一种是三个点都在 \(u\) 子树内的,一种是 \(2\) 的点在 \(u\) 子树内,一个在外。
然而这样还是 \(O(n^2)\)。因为状态数与深度有关,考虑长链剖分。
长剖的过程是这样的:每次直接继承重儿子的信息,合并轻儿子暴力。
由于每个点只会在重链顶端暴力合并,所以时间复杂度为 \(O(n)\)。
再用指针分配内存,做到空间复杂度 \(O(n)\)。
P10408 「SMOI-R1」Apple
其中一个 subtask 的做法是操作分块,每次询问直接暴力计算块内修改的贡献,每个块结束重构一遍。
回到正解,我们从 OR-FWT 的过程出发。
我们如果每次修改,都做一遍完整的 fwt,每一次就得 \(O(n2^n)\),然而查询 \(O(1)\),启示我们去平衡。
所以我们每次单点修改,都从分治树底向上做 \(n/2\) 层。
然后我们每次查询的时候,查询的是 \(x\),那么 \(x+k2^{n/2}\) 的点才能做贡献,继续分治上去即可。
已经完成平衡,每次操作复杂度是 \(\frac{n}{2}\cdot 2^{\frac{n}{2}}\)。
P8456 「SWTR-8」地地铁铁
图上的路径考虑转成树。考虑圆方树。
若两个点在不同的点双中,我们只需要判断,路径上的方点是否两个颜色都有。
但是两个点在同一个点双中呢,可能这个点双中有两种颜色,但是没有经过两种颜色的路径。
比如说 \(u,v\) 在一个点双中,两条不相交路径,一条白,一条黑。
我们仔细的观察,一个点双中,若有两种颜色,一定有一个黑白环。
那么环外的两点路径,把环看成一个点,任意点到这个环都有两条路。一个点先来找环,再从环回去。
环外到环上同理。问题是环内的路径,若环是有一段黑和一段白拼起来,黑白交接的两个点间怎么走。
这两个点若环外还存在一个点黑白相接即可走。所以不合法的是黑白相接的点个数 \(=2\).
我们减去点双内不合法的,再统计不在一个点双内的,容斥,减去只能走一种颜色的路径,并查集。
P3647 [APIO2014] 连珠线
考虑整个过程是怎么样的。整个过程都是一棵树,每次都加入两条相连的蓝边,所有两条蓝边不交。
我们可以钦定第一个点然后去 dp,这样两条蓝边都是祖先链。
设 \(f_u\) 表示 \(u\) 点还差一条蓝边配对的方案数,\(g_u\) 表示 \(u\) 点没有欠配对的蓝边的方案数。
换根 dp 即可,维护最大值和次大值。
P3643 [APIO2016] 划艇
如果设 \(f_{i,j}\) 表示填到 \(i\),\(i\) 填的是 \(j\) 的方案数,转移枚举上一个填了的地方。然而 \(a,b\) 太大了。
考虑离散化。设 \(f_{i,j}\) 表示填到 \(i\),\(i\) 填的数落到第 \(j\) 个区间的方案数。
转移是麻烦的,因为 \(i\) 填到第 \(j\) 个区间里,\(i\) 前面的数也可以填到第 \(j\) 个区间里,我们如何计算呢。
我们设 \(j\) 区间由 \([p+1,i]\) 的数来填,枚举有 \(k\) 个数非零,设 \(m\) 表示 \([p+1,i]\) 里能填 \(j\) 区间个数,\(C_m^k\)。
这 \(k\) 个数递增,设区间 \(j\) 长度为 \(len\),\(C_{len}^k\),由于 \(i\) 必填,范德蒙德卷积 \(\sum_{k\ge 1}C_{m-1}^{k-1}C_{len}^k=C_{m+len-1}^m\).
所以所有的 \(k< j\),\(f_{p,k}\) 对 \(f_{i,j}\) 的贡献是 \(C_{m+len-1}^m\),前缀和优化一下。
组合数巨大,但是对于同一个 \(f_{i,j}\) 可以递推。
P9676 [ICPC2022 Jinan R] Skills
如果一个技能练习了,但又掉回 \(0\) 熟练度,那么不如不练习。
所以最佳方案中每个熟练度,是不会出现中途 \(\le 0\),所以减贡献的时候不需要跟 \(0\) 取 \(\max\).
设 \(f_{i,j,k}\) 表示三个技能上次练习距今 \(i,j,k\) 天的最大价值,\(i,j,k\) 有一个 \(=0\),转移 \(O(1)\),状态 \(O(n^3)\)。
考虑优化状态,注意到减贡献是平方增长的,盲猜连续不练习根号天。
假设连续不练习了 \(x\) 天,消耗量是 \(\frac{1}{2}(x^2+x)\),这 \(x\) 天里另外的技能增加量是 \(ax\),虽然不亏但不优。
假设我们在第 \(y\) 天练习了,那么就会减少 \((x-y)y\) 的消耗量,但是减少了 \(a\) 的增加量。
当 \(x\ge 2\sqrt a\) 时,取 \(y=\sqrt a\),这样一定更优,所以最多不练习 \(2\sqrt a\) 天。
复杂度是 \(O(na)\).
P8860 动态图连通性
这个题显然是要离线做的,我们设每条边被操作的时候是 \(t_i\).
我们最后一定会仅剩下一条 \(1\sim n\) 的路径。这条路径有什么性质呢?
考虑跟另外一条来比较,假设 \(1\sim n\) 的路径中有两个点 \(u,v\),挂了一条路径 \(u\Rightarrow v\)。
\(1\to u\to v\to n\)(记为路径 \(1\)),优于 \(1\to u\Rightarrow v\to n\)(路径 \(2\)),只用考虑 \(u\) 到 \(v\) 的路径的差异。
如果路径 \(1\) 更优,那么肯定路径 \(2\) 中有一条边被提前删除了。
设路径 \(1\) 的边的 \(t\) 的集合为 \(S_1\),路径 \(2\) 的边的 \(t\) 的集合为 \(S_2\),那么 \(S_1\) 字典序大于 \(S_2\).
所以我们考虑用 dijkstra 算法求这条最优路径,两种路径的比较就二分哈希,集合的维护用主席树。
P7207 [COCI2019-2020#3] Sob
二进制考虑拆位,假设从高到低拆位,每次将 \(A,B\) 集合分成两份,一份为 \(0\),一份为 \(1\)。
发现 \(|A_0|\ge |B_0|\),那么我们必须得从 \(B_1\) 调一些到 \(B_0\),但是不知道调哪些。
从低到高拆位,也就是奇偶性,发现 \(|A_0|\ge |B_0|\),且 \(|A_0|-|B_0|\le 1\)。
因为此时 \(|B|\) 一定是奇数,所以把 \(B_1\) 中第一个调给 \(B_0\),分为大小一半的子任务,这样做是合法。
因为两个大小相同的区间一定能匹配,把 \(B_1\) 第一个调给 \(B_0\),去掉最后一位后还是连续区间。