1 条题解
-
0
题目理解
我们有两个长度为 的数组 和 ,可以对任意下标 交换 和 任意次。定义 为数组 中不同数字的个数,目标是最大化 ,并输出达到最大值时的两个数组。
关键观察
对于任意一个数值 :
- 如果 在 和 中都不出现,它对答案贡献为 。
- 如果 恰好出现一次,无论怎么操作,它一定出现在某个数组中,贡献为 。
- 如果 出现至少两次,它的贡献可以是 或 :
- 如果所有出现都在同一个数组中,贡献为 。
- 如果两个数组都包含 ,贡献为 。
设 为 在 和 中的总出现次数,那么 对答案的贡献不超过 。
因此,答案的上界是:
并且这个上界是可以达到的。
建模为图论问题
对于每个下标 ,我们在 和 之间连一条无向边。这样得到一个图,顶点是数值(范围 到 ),边对应数组中的位置。
目标:给每条边定向(方向表示哪个值在 中,哪个在 中),使得:
- 对于度数 的顶点,至少有一条出边(该值在 中出现)。
- 对于度数 的顶点,至少有一条入边(该值在 中出现)。
如果满足这个条件,那么:
- 度数为 的顶点:不影响答案。
- 度数为 的顶点:唯一的一条边定向后,该值一定只出现在一个数组中,贡献 。
- 度数 的顶点:因为既有入边又有出边,该值一定在两个数组中都出现,贡献 。
这样恰好达到上界 。
构造方法
第一步:DFS 树定向
对每个连通分量,任选一个根做 DFS 树。
- 将树边从上到下定向(从父节点指向子节点)。
- 将返祖边(back edges)从下到上定向(从子节点指向祖先)。
这样处理后:
- 非根节点:因为有父节点指向它的树边,所以有入边;同时因为它至少有向子节点的边(或返祖边),所以有出边。条件满足。
- 根节点:可能有出边(指向子节点),但不一定有入边。如果根节点度数 却没有返祖边进入它,则不满足条件。
第二步:处理根节点
如果根节点度数 且没有返祖边进入它,那么它至少有 个子树。选择其中一个子树,将该子树内所有边反向。这样:
- 根节点获得一条来自该子树的入边。
- 子树内的节点原本满足条件,反转后仍然满足(因为原先是双向的,反转后入边变出边,出边变入边,仍满足既有入边又有出边)。
第三步:实现细节
标程中分两次 DFS:
- 第一次 DFS(
used[v] > 0的调用):从度数为 的顶点开始,保证这些端点被正确处理。 - 第二次 DFS:处理剩余的连通分量(可能是环或没有度数为 的点的分量),找到环上的一个起点(
rt),然后从该点开始定向。
make函数用于定向:如果位置 还没被处理,就根据需要的方向交换 和 ,并标记已处理。
算法复杂度
- 每个顶点(数值)最多有 个,每条边(下标)有 条。
- 建图 。
- DFS 遍历 。
- 总复杂度 每个测试用例。
总结
这道题的核心是:
- 推导出答案的上界 。
- 将问题转化为图的边定向问题,要求每个度数 的顶点既有入边又有出边。
- 用 DFS 树加特殊处理根节点的方法构造出达到上界的定向方案。
- 1
信息
- ID
- 6562
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者