1 条题解
-
0
自动搬运
来自洛谷,原作者为

littleKtian
MoVe yoUR BoDy搬运于
2025-08-24 22:22:13,当前版本为作者最后更新于2020-03-14 21:36:55,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
upd on 2021.10.2: 修复了代码的问题。
upd on 2021.1.31: 修改了对 Subtask 3 做法的描述。
题外话
这题第二部分做法来自某次校内模拟赛,出题人对其进行了一定的改动。
题意
给定一棵树,定义数对 合法当且仅当对于所有序号在 之间的点构成的顶点导出子图中不存在一条路径长超过 的路径。每次询问 ,求满足 且合法的 对数及所有的 之和。
可以证明,如果 不合法,那么 和 一定也不合法。
假设我们已经求出对于所有的 最小的不合法的 ,即为 。根据上面的性质,可以发现 刚好构成一条单调不下降序列。
对于每个询问 ,可以分成 和 两部分处理。因为有如上性质,可以发现两部分刚好是连续的。
第一部分可以利用前缀和优化,第二部分因为存在规律,可以根据长度直接推公式。
每个询问处理复杂度为 (二分寻找两部分分割点)。
考虑如何求 。
容易得到下面的思路:
在树上找出所有长度为 的路径,假设该路径序号最小的点序号为 ,序号最大的点序号为 。则 应为所有的 中的最小值。全部统计完以后再从后往前取最小值即可得到 。
伪代码如下:
void ss()//找路 { 找到一条路 rq[a]=min(rq[a],b); } int main() { for(int i=1;i<=n;i++)rq[i]=n+1; 不断找路 for(int i=n-1;i>0;i--)rq[i]=min(rq[i],rq[i+1]); }
Subtask 1:
枚举路径起点暴力 dfs 即可。
复杂度 。
Subtask 2:
既然是链肯定有一些性质。出题人懒得写了。
Subtask 3:
对于两条长度都为 的路径,假设第一条路径中序号最小和最大的点序号分别为 ,另一条为 ,如果 且 ,那么可以不考虑第二条路径,从而减少枚举数量。
考虑点分治。
用平衡树记录每层以根为一个路径端点的路径长为 的所有路径中序号最大和最小的点的序号(假设为 ),并利用如上性质维护(如果存在另一个长度相同且所包含点的区间被其包含,那么就可以将这条路径从平衡树中删除)。此时平衡树内的两个序列都是单调递增的。对于每次 dfs 得到的路径,显然最后组合出的长为 的路径所包含点的区间必然包含 ,因此只需要在平衡树内找到所有长度为 的路径中最小点序号大于 且最小的路径(即 的后继)和最大点序号小于 且最大的路径(即 的前驱),让之前 dfs 得到的路径与分别与这两条拼接即可。而对于其中所包含点的区间包含 的长度为 的路径,可知其组出的区间已经达到最优,因此可以直接将其从平衡树内删除。
总复杂度为 ,常数略大。
代码(略长,但其中很多都是板子):
- 1
信息
- ID
- 5209
- 时间
- 1000~4500ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者