loj#P4818. 「KTSC 2025 R2」进化 2
「KTSC 2025 R2」进化 2
注意事项
在 LibreOJ 上,由于语言限制,目前只支持以下语言的提交:
- C++(标准为 C++ 17 及以上)
请在提交源代码前添加 #include "evolution2.h"
。
题目描述
题目译自 2025년도 국제정보올림피아드 대표학생 선발고사 - 2차 선발고사 T1 「구재현」
我们正在研究生物的进化历程。除了最初的生物外,所有生物都由已存在的生物进化而来。我们把已存在的生物称为父母生物,新诞生的生物称为子生物。
个生物各有一个独一无二的出生编号,范围从 到 。这些编号按生物诞生的顺序分配,因此父母生物的出生编号总是小于子生物的编号,而最初生物的出生编号为 。
生物通过进化诞生的过程可以用一个树形结构来表示:生物是树中的节点,进化关系是连接父母生物和子生物的边,最初生物作为树的根。这个结构被称为进化树。
例如,假设最初编号为 的生物进化出编号为 和 的生物,编号 的生物进化出编号 、、 的生物,编号 的生物进化出编号 的生物,而编号 的生物又进化出编号 和 的生物,这样的进化树如下图所示,每个节点标有生物的出生编号。
但不幸的是,你的珍贵进化树被教练赵英旭不小心洒上了咖啡。咖啡浸湿后,进化树的形状和最初生物(编号 )还能辨认,但除最初生物外的其他生物的出生编号已无法识别。
赵教练赶紧给每个生物临时编了个编号:最初生物的临时编号仍为 ,其余 个生物被随机分配了 到 的不同编号。这些临时编号可能与出生编号相同,也可能不同,且不像出生编号那样保证父母生物的编号小于子生物。
例如,同一进化树可能被临时编号如下图所示,每个节点标有临时编号。
幸运的是,赵教练的笔记本里存有进化树的备份,但备份文件被加密,他忘记了密码。好在备份程序还能用。程序提供了一个功能:输入两个生物的临时编号,它会告诉你哪个生物的出生编号更小。但若频繁使用这个功能,赵教练那台性能低下的笔记本可能会崩溃。因此,你需要帮助赵教练编写代码,用尽量少的查询次数恢复进化树中所有生物的出生编号。
实现细节
你需要实现以下函数:
std::vector<int> recover(int N, std::vector<int> U, std::vector<int> V)
- 该函数在一次执行中可能被调用多次。
U, V
:长度为 的整数数组。对于任意 ,表示进化树中临时编号为 的生物是父母,临时编号为 的生物是子生物。所有 互不相同。- 你需要在每次调用中,通过调用后续定义的
compare
函数(可调用 次或多次),找出进化树中每个生物的出生编号,并将其存入一个大小为 的std::vector
返回。设返回值为 ,则对于所有 ,临时编号为 的生物的出生编号应为 。
程序可调用以下函数:
int compare(int a, int b)
- 和 必须满足 且 。
- 若临时编号为 的生物的出生编号小于临时编号为 的生物的出生编号,返回 ;否则返回 。
你提交的代码不得包含任何输入输出函数。
样例
假设 ,,。评测程序调用:
recover(4, [0, 0, 0], [1, 2, 3])
树的结构如下图:
假设出生编号如下:
- 临时编号 :出生编号 (固定)
- 临时编号 :出生编号
- 临时编号 :出生编号
- 临时编号 :出生编号
初始时,可能的出生编号排列有 $[0,1,2,3], [0,1,3,2], [0,2,1,3], [0,2,3,1], [0,3,1,2], [0,3,2,1]$,共 ,故 。
通过以下调用:
compare(1, 2)
返回 ()compare(2, 3)
返回 ()compare(1, 3)
返回 ()compare(0, 3)
返回 ()
调用 次后返回 ,结果正确。此时 ,,得满分。此样例满足子任务 和 的条件。
数据范围与提示
对于所有输入数据,满足:
- 对于所有 :
- 输入数据构成一个有效的进化树。
- 一次执行中所有
recover
调用中 的总和不超过 。 - 本题的评测程序是非自适应的(NOT adaptive),即各生物的出生编号在程序开始时已固定,不会因
compare
调用而改变。
详细子任务附加限制及分值如下表所示。
子任务 | 分值 | 附加限制 |
---|---|---|
进化树中不存在与三个以上生物相邻的生物,且最初生物只与一个生物相邻 | ||
对于所有 , | ||
可为进化树中的每个生物重新分配一个颜色 ,使得对于所有 ,颜色为 的生物的父母颜色为 ,且存在正整数 满足 。即进化树是完全二叉树 | ||
无附加限制 |
每次 recover
调用按以下方式评分。各子任务的得分取该子任务内所有测试用例中 recover
调用得分的最小值:
-
若程序异常终止或
recover
返回值错误,得 分。 -
在未知
compare
提供的编号大小关系及子任务限制时,对于 ,临时编号为 的生物的出生编号为 的可能排列 ( 的顺序)数量记为 。因正确答案也是可能的 之一, 为正整数。定义 , 为本次调用中compare
的调用次数。得分由 决定。若 导致 未定义,则当 时 ,当 时 。 -
若 ,得 分。
-
若 ,得该子任务分数的 %。
-
若 ,得该子任务分数的 %。
-
若 ,得该子任务分数的 %。
-
若 ,得该子任务分数的 %。
-
若 ,得该子任务分数的 。
示例评测程序
示例评测程序接收测试用例数量 ,随后接收 组输入,每组包括:
- 第 行:
- 第 行:
- 第 行:
其中:
- :出生编号为 的生物的父母出生编号,满足 。
- :出生编号为 的生物的临时编号,,且 是 的排列。
对每个测试用例,程序根据进化树构造 和 ,调用 recover
,并输出:
- 若
compare(a, b)
的 不满足 ,输出Wrong Answer [1]
。 - 若 ,输出
Wrong Answer [2]
。 - 若
recover
返回数组长度不为 ,输出Wrong Answer [3]
。 - 否则,第一行输出
C: 4
( 为compare
调用次数),第二行输出recover
返回值 的元素。
输出 Wrong Answer
后程序立即终止。
注意,正确输出应满足 ,但示例程序不验证这一点,且可能与实际评测程序不同。