杂题选做-3
#21 P9755
首先,看上去这个题直接不是很友好,我们考虑二分转为判断性问题。
然后一个这类在树上 topo 遍历每一个节点的最优方案类问题有一个 Trick:我们找出当前最优的节点,将其与其父亲合并。
具体地,在确定一个答案 \(T\) 之后,我们可以在 \(O(1)\) 的时间内求出或通过二分在 \(O(\log n)\) 的时间内每一个点的最晚访问时间 \(t_i\)。具体地,我们可以先预处理每一个节点的一次函数值什么时候小于 \(1\),优先统计 \(1\) 的贡献,然后对剩余部分我们就考虑对 \(b_i\) 和 \(c_ix\) 分别求和。
然后我们只需要考虑两个问题:
-
怎么判断一个节点是否比另一个节点更优(确定排序规则);
-
怎么合并一个节点和其父亲;
我们优先思考第二个问题。我们在合并完一个节点后,这个新节点的最晚的访问时为 \(t_i-1\)。因为 \(t_i\) 是合并前的最小时间点,所以 \(t_i-1\) 也一定是合并后的最小时间点。
因此我们发现可以简化上述流程:直接找到当前时间点最小的点,然后直接把它到根的所有未访问点访问。
时间复杂度为 \(O(n \log V \log n)\),可以通过数学推导优化到 \(O(n \log V)\)。
#22 P8817
看到 \(n \le 2500\),且边权为 \(1\)。我们就知道可以在 \(O(n^2)\) 的时间内用 bfs 预处理出任意两点间的距离。
然后我们考虑一个问题,假如我们确定了 \(b,c\),那么我们希望取到 \(b\) 可达的点中,权值最大的点,和 \(c\) 可达的点中,权值最大的点。
但是这两个点可能相同,或者与 \(b,c\) 相同,但是可以确定的是,我们只需要枚举前 \(3\) 大的节点即可。
时间复杂度为 \(O(n^2)\)。
#23 AGC036F
注意到限制的形式类似于圆的标准方程,于是我们将其转化为:“在第一象限,以原点为圆心,半径分别为 \(n\) 和 \(2n\) 画两个 \(1/4\) 圆,然后圆环部分放 \(2n-1\) 个车,使得它们不能互相攻击”。
其中排列转化为放车是经典Trick。
这是一个每一个元素有上下界的问题,我们考虑将其转化为无下界,然后容斥的问题。(想到这一步是因为每一个非法方案也是一个前缀)
根据几何知识,第 \(i\) 个元素的上下界 \([L_i,R_i]\),为 \(L_i=\lceil\sqrt{n^2-i^2}\rceil,R_i=\lfloor\sqrt {4n^2-i^2}\rfloor\),这里你应该也看出来了,只有 \([0,n)\) 的元素是有下界的。
我们先考虑求出没有限制的答案。我们按上界从小到大来考虑每一个元素的决策,因为这样可以保证每一次当前决策一定会影响后面。我们假设升序排序后的 \(R\) 为 \(r\),那么答案为 \(\prod \limits_{i=0}^{2n-1}r_i-i+1\)。
那么我们考虑类似上述方法容斥。
显然的,假设有 \(k\) 个元素的上界为 \(L_i-1\) 的贡献为 \(f_k\),那么对答案的贡献就是 \((-1)^kf_k\) 。
类似上述做法,我们考虑维护按上界排序,其中 \([0,n)\) 的元素按 \(L_i-1\) 排序,\([n,2n)\) 的元素按 \(R_i\) 排序。(显然,为了保证前面一定影响后面,你需要另一端设为第二关键字)
我们考虑对每一个 \(k\) 单独 dp 一次。我们设 \(f_{i,j}\) 为考虑了前 \(i\) 个元素,且有 \(j\) 个元素的上界为 \(L_i-1\) 的合法方案数。显然,存在初始状态 \(f_{0,0}=1\)。接下来讨论转移:
如果该元素在 \([n,2n)\) 内:
-
那么它原本有 \(R_i+1\) 个选取方案;
-
因为排序,所以它前面选 \(L_i-1\) 为下界的元素和没有下界的元素都会限制它的选取,这里的总数为 \(j+c_0\),其中 \(c_0\) 为前面没有下界的元素,这个在转移时直接统计即可。
-
那么这个转移为 \(f_{i+1,j} \leftarrow f_{i,j} \times(R_i+1-j-c_0)\)
如果该元素在 \([0,n)\) 内,且选择 \(L_i-1\) 为上界:
- 这里的讨论类似上文,不再赘述;
- 转移为 \(f_{i+1,j+1} \leftarrow f_{i,j} \times (L_i-j-c_0)\)。
如果该元素在 \([0,n)\) 内,且不选择 \(L_i-1\) 为上界:
-
它原本有 \(R_i+1\) 个选取方案;
-
因为 \(L_i\) 最大为 \(n\),在 \([0,n)\) 内 \(R\) 最小为 \(\sqrt 3n\),所以每一个选取上界为 \(L_i-1\) 的元素都会限制它的选取,这类限制个数为 \(k\)。
-
因为此时 \(R_i\) 一定大于 \([n,2n)\) 内的每一个 \(R_i\),因此这类限制个数为 \(n\)。
-
如果之前有下界的元素选取 \(R\) 作为上界,因为排序,这类元素也会对 \(i\) 有限制,这类限制的个数为 \(c_1-j\),其中 \(c_1\) 为之前有下界的元素个数。
-
转移为 \(f_{i+1,j} \leftarrow f_{i,j} \times(R_i+1-k-n-c_1+j)\)。
时间复杂度为 \(O(n^3)\)。
#24 P8819
下位紫,看懂题目是最大难点。
首先我们考虑形式化题意:
给定一个 \(n\) 个点 \(m\) 条边的有向图连通图,你需要支持:
-
禁用(启用)一条边;
-
禁用(启用)到达一个点的所有边;
每一次操作后询问图上是否每一个点的出度都为 \(1\),且每一个点沿着边走都可以达到一个环。
显然,“每一个点出度为 \(1\)” 是 "每一个点沿着边走可以到达一个环" 的充分条件,所以我们只需要判断每一个点的出度是否为一即可。
这个限制很弱,我们直接随机赋值然后 Hash 判断即可,支持操作也是简单的。
#25 P4719
动态 dp 就是把转移写成广义矩乘的形式,然后利用数据结构维护每一个位置的转移矩阵和区间的矩阵值,实现快速更新 dp 值。
本题中,如果没有修改,我们会设 \(f_{i,0/1}\) 表示 \(i\) 点不取/取时的最大权独立集权值。显然有f
接下来,为了实现修改,我们给这棵树套上一个树剖,然后把 dp 改成我们常见的树剖形式。具体地,我们定义 \(f_{u,0/1}\) 表示 \(i\) 点不取/取时的最大权独立集权值,\(g_{u,0}\) 表示 \(u\) 的轻儿子都不取且 \(u\) 取的最大权;\(g_{u,1}\) 表示 \(u\) 不取时在轻子树内取到的最大权。我们令 \(son_u\) 为 \(u\) 的重儿子,那么有:
那么我们可以看出来这是从 \(son_u\) 转移到 \(u\)。因为加法对 \(\max\) 运算具有结合率,所以我们可以套广义矩乘。然后因为在线段树上,乘法的顺序是由链顶到链尾的,也就是说我们是左乘上一个矩阵,然后我们可以设计出转移:
然后我们考虑一下我们在修改时,除了修改当前点的矩阵,我们还要跳链,在链顶处修改父亲的 \(g\) 值。
时间复杂度为 \(O(Mn\log^2 n)\),其中 \(M\) 是矩阵乘法的时间复杂度,为 \(8\)。
#26 P8820
多次询问,考虑 ddp。因为无修,所以我们可以预处理每一个节点的矩阵,然后倍增预处理向上跳 \(2^k\) 步后得到的矩阵积和逆序后的矩阵积。
因为 \(k \in \{1,2,3\}\),所以让我们分类讨论。
如果 \(k=1\):那么就直接是路径上的点权和;
如果 \(k=2\):注意到此时我们只会经过路径上的点,然后直接 dp 即可;
如果 \(k=3\):那么此时我们用 \(f_{i,j}\) 表示到路径上第 \(i\) 个点,且转移时从距离 \(i\) 为 \(j\) 的位置转移过来的最小权值和。
转移是简单的,写成矩阵形式后预处理即可。
#27 P8860
首先,我们注意到:一条边只可能在第一次被询问到时被删除。
这是显然的,因为如果第一次询问没有被删除,那么说明它已经在 \(1 \rightarrow n\) 的必经之路上,那么在之后这个性质不会消失,所以之后的询问不可能删除它。
我们定义 \(t_i\) 为第 \(i\) 条边可能被删除的时间,如果第 \(i\) 条边没有被询问过,那么 \(t_i=q+i\)。这样我们 \(t\) 就有很好的性质:\(t_i\) 互不相同。
然后题目其实就是要求一条路径,使得路径上所有边的 \(t_i\) 升序排序后形成的序列的字典序尽可能大。
然后我们有一个很自然的贪心:从大到小的加入每一条边,如果在某一次加边时 \(1\) 和 \(n\) 连通了,那么此时的方案就是字典序最大方案。
那么怎么构造方案呢,我们这么想:从 \(1\) 出发,我们可以沿着 \(1\) 的每一条出边到若干个点,那么在这些点之中,经过边 \(t_i\) 最大的点一定是最优的,于是我们从这个点继续扩展,然后又得到一些新点。那么这个时候我们应该扩展哪一个点呢?
答案不太显然:扩展到这个点的边 \(t_i\) 最小的点。
为什么?因为字典序的大小首先是要比最小元素的大小,我们令上述点为 \(u\),扩展到 \(u\) 的点为 \(pre_u\),如果去扩展一个其他的点 \(v\),那么因为 \(t_u>t_v\),所以至少从现在来看,\(v\) 是劣于 \(u\) 的。
可能有人会问:那万一 \(1\) 到 \(u\) 路径上的最小值小于 \(1\) 到 \(v\) 路径上的最小值呢?其实这并不影响。因为 \(v\) 能和 \(u\) 进行比较而不是直接扩展 \(v\),说明 \(1\) 到 \(pre_u\) 路径上的最小值也大于 \(pre_v \rightarrow v\) 的 \(t\)。
综上,我们只需要每一次扩展经过 \(t\) 最大的点即可。
#28 ARC186D
题目有点唬人。
我们观察合法序列的构造,发现这东西有点像树。具体地,我们把 \(A_i=0\) 看做叶子,然后 \(A_i=x\) 表示他有 \(x\) 个儿子。
那么我们可以有以下推论:
-
\(\forall_{1 \le x \le n-1} \sum \limits_{i=1}^x A_i \ge x\):如果不满足这一条件,说明前 \(x\) 个点内的边数少于点数,那么就说明前面无法构成一颗树;
-
\(\sum \limits_{i=1}^n A_i=n-1\):一颗树有 \(n-1\) 条边。
条件一对每一个 \(x\) 都有限制且限制值的变化量一定,那么我们可以把这个东西转化为格路问题。
我们可以把条件一转化为不能触碰 \(\forall_{x\in[1,n-1]}(x,x)\),然后出发点为 \((0,1)\)。在横坐标为 \(i\) 时:先向上走 \(A_i\) 格,然后再向右走 \(1\) 格。最终要走到 \((n,n)\)。问题转化为统计从出发点走到终点的合法路径数。
那么我们现在先考虑一下字典序的限制。类似数位 dp,我们枚举 \(A\) 的前缀,对每一个前缀 \(i\) 统计 \(B=[A_1,A_2,A_3,\cdots,A_{i-1},b](0 \le b <A_i)\) 的合法序列 \(B\) 的个数。
也就是说我们从 \((i,\sum \limits_{j=1}^{i-1}A_i+b)\) 出发,到 \((n,n)\) 的合法路径数。这个直接求不是很好求,我们考虑容斥。
我们定义 \(f(x_1,y_1,x_2,y_2)\) 表示从 \((x_1,y_1)\) 到 \((x_2,y_2)\) 不考虑限制的路径数,等于在长度为 \(x_2-x_1+y_2-y_1\) 的操作序列上选取 \(x_2-x_1\) 个向右操作,为 \(\large \binom{x_2-x_1+y_2-y_1}{x_2-x_1}\)。
那么由反射容斥的思想可以得到合法的路径数为 \(f(x_1,y_1,n-1,n)-f(y_1,x_1,n-1,n)\)。(这里是 \((n-1,n)\) 的原因是如果选 \((n,n)\) 的话减去的路径不全是非法的)
#29 CF1039D
首先,看到这类题,我们要先想对于一个确定的 \(k\),怎么求它的答案。
我们看到一个子树内,如果它有两个以上的儿子,并且可以构成一个长度大于等于 \(k\) 的链,那么我们就直接在子树内合并成链;如果没有,那么就传递到父亲。这样就有时间复杂度为 \(O(n)\) 的算法。
然后,看到 \(10^5\) 的数据范围和 \(7s\) 的时间限制,引导我们往根号级算法上靠。
对于这一道题,我们发现对于一个 \(k\),它的答案不大于 \(\dfrac{n}{k}\),这引导我们考虑根号分治。
我们设闸值 \(T\),那么当 \(k \le T\) 时,我们可以直接暴力求解,时间复杂度为 \(O(Tn)\);当 \(T < k \le n\) 时,注意到此时答案不大于 \(\dfrac{n}{T}\),二分查找每一个答案对应的区间即可,时间复杂度为 \(O(\dfrac{n^2\log n}{T})\);平衡一下复杂度,当 \(T=\sqrt {n \log n}\) 时,时间复杂度为 \(O(n\sqrt{n \log n})\)。
#30 P7565
首先,如果我们已知 \(p\),那么答案就是这个 \(P\) 个点的带权重心。那么如果 \(P\) 是奇数,那么答案显然为 \(1\),因为重心可以从 \(u\) 转移到它相邻的点,当且仅当它左右两边的儿子数量相同。
当 \(P\) 是偶数时,它的重心个数最大值就是 \(\max dis_{u,v}\),其中 \(sz_u,sz_v \ge \dfrac{P}{2}\),且 \(u,v\) 的子树无交。

浙公网安备 33010602011771号