这是一道交互题。
给出五元组
是一棵 个点的有根树 ,其中 为 的点集, 为 的边集。树的节点被编号为 ,其中根节点编号为 。 是一个集合,集合中的元素称作信息。其中有两个不同的特殊元素:单位元 和不合法信息 。
对于一般的信息,其都具有点集合和边集合两个属性。特别的,对于单位元,其只有边集合的属性,而对于不合法信息,其没有以上两种属性。
- 对于信息
, 的点集合是 的一个二元子集,记作 ,满足 且 。其中,两个集合 的差 被定义为 。 - 对于信息
, 的边集合是 的一个子集,记作 ,满足 。规定单位元的边集合为空,也即 。 - 对于树上的任何一条边
,记 ,存在一个关于 的信息 ,它以其端点为点集合、自身为边集合,即 , 。
信息有两种合并的方式,分别记作
- 单位元和任何信息合并都得到对方。也即,如果
,那么 ;如果 ,那么 。 - 不合法信息和任何信息合并都得到不合法信息。也即,如果
或者 ,那么 。 - 对于剩下的情况,如果两个信息的边集合的交集非空,或者点集合的交集的大小不为
,则合并得到不合法信息。也即,如果 或 ,则 。 - 否则,有
其中 表示集合的对称差运算,也即 。
定义
给出评分参数
每组询问中,你需要在
实现细节
请确保你的程序开头有 #include "count.h"
。头文件 count.h
中实现了如下内容:
- 定义了信息对应的数据类型
info
; - 定义了
所对应的info
类型常量emptyinfo
,你可以在程序中直接使用。 - 定义并实现了以下两个信息合并函数,你可以在程序中直接调用:
info MR(info a,info b);
info MC(info a,info b);
- 两个函数分别返回
与 对应的信息。
你需要保证调用
- 定义并实现了判定一个信息是否为单位元的函数,你可以在程序中直接调用:
bool isempty(info a);
- 这个函数返回真当且仅当
为单位元。
可以查看参考交互库了解更多实现细节。
你不需要,也不应该实现主函数。你需要实现如下几个函数:
void init(int T, int n, int q, vector<int> fa, vector<info> e, int M);
表示测试点编号, 表示树的点数, 表示询问数, 表示该测试点的评分参数。fa
和e
的长度均为 。对于 , 和 为第 条边 的两个端点, 为题目描述中提到的 所对应的info
类型元素。数据保证 小于 。
info ask(int u, int d);
- 给出一个询问,参数的意义见题目描述。你需要在函数结束时返回一个满足题设条件的信息。
最终测试时,在每个测试点,交互库会恰好调用一次 init
函数,随后调用 ask
函数。交互库会使用特殊的实现方式,单个 info
类型的变量会恒定消耗 info
类型变量同时存在。
保证在满足调用次数限制且不进行 isempty
函数调用的情况下,最终测试的交互库运行所需的时间不超过 isempty
函数调用的情况下,最终测试的交互库运行的时间不超过
在下发文件中包含一个名为 count.cpp
的文件,作为示例程序,选手可以在此基础上继续实现本题。在下发文件中还额外包含一个名为 count_backup.h
的备份文件,我们保证其与
count.h
文件完全相同。
测试程序方式
本题目录下提供了两个交互库的参考实现 grader.o
, checker.o
, 其为两个不同的交互库编译产生的可链接文件。最终测试时所用的交互库实现与该实现有不同,因此选手的解法不应依赖交互库的具体实现,同时也不应该依赖 count.h
中 info
类型的具体实现。
你需要修改下发的 count.h
来帮助进行链接。具体的,在将源代码 count.cpp
和程序 grader.o
进行链接的时候,你需要注释掉 count.h
代码的第 checker.o
方法类似,需要注释掉 count.h
代码的第 count.h
的实现自行修改来实现不同程序的编译。
修改后,选手可以在本题目录下使用如下命令编译得到可执行程序:
g++ count.cpp ‐c ‐O2 ‐std=c++14 ‐lm && g++ count.o grader.o ‐o count
g++ count.cpp ‐c ‐O2 ‐std=c++14 ‐lm && g++ count.o checker.o ‐o count
其中第一行命令会编译当前 count.cpp
后与 grader.o
链接起来,生成可执行文件 count
,第二行命令则会编译当前 count.cpp
后与 checker.o
链接起来,生成可执行文件 count
。
按上述方法编译得到的可执行文件 count
,其运行方式如下:
- 可执行文件将从标准输入读入以下格式的数据:
- 第一行四个整数
,分别表示测试点编号、树的点数、询问数和评分参数; - 第二行
个整数 ,分别表示 至 的父亲节点编号,在本地调试时你需要保证 ; - 接下来
行每行两个整数 ,描述一次询问。
- 第一行四个整数
- 读入之后,交互库会进行测试。如果你的程序不满足交互库限制,其会在输出中返回对应的错误信息。否则,对于链接的可执行文件,其输出如下:
- 总共一行三个整数
,其中: 表示程序在init
函数中调用交互库函数的总次数; 表示程序在运行过程中调用交互库函数的总次数; 表示程序在 次ask
函数中调用交互库函数的次数的最大值。- 对于上述三个统计量,我们只会计入
MR
、MC
函数的调用次数,而不会计入isempty
函数的调用次数。
- 在链接不同文件的时候,其能够进行的检查也不同,具体的:
grader.o
: 其在运行时不会检查ask
函数返回的信息是否正确,但可以帮助选手判断交互操作是否符合要求。这份程序运行时间最接近评测时的交互库,因此选手可以利用该程序测试运行速度,但不保证程序正确性。checker.o
: 其在运行时会检查ask
函数返回的信息是否正确,也可以帮助选手判断交互操作是否符合要求。同时其会检查ask
函数返回的信息是否正确。这份程序可以进行答案正确性的检查。
- 总共一行三个整数
选手在调试时需要保证输入可执行文件 count
的数据满足上述输入格式,否则不保证输出结果正确。
样例一
见附件下载。
样例二
见附件下载。
该组样例满足数据范围中的特殊性质 A。
样例三
见附件下载。
该组样例满足数据范围中的特殊性质 B。
样例四
见附件下载。
评分方式
最终评测只会收取 count.cpp
,修改选手目录下其他文件不会对评测结果产生影响。注意:
- 未初始化的
info
类型的变量不保证是emptyinfo
。 - 请不要尝试访问或修改
info
类型的成员变量,否则将被视为攻击交互库。 - 请不要在
init
函数调用之前调用MR
和MC
函数,否则可能会发生未定义行为。 - 你只能访问自己定义的变量和交互库返回的
info
类型变量 ,尝试访问其他空间将可能导致编译错误或运行时错误。
本题首先会受到和传统题相同的限制,例如编译错误会导致整道题目得
在上述条件以外,在一个测试点中,若程序执行了非法的函数调用或询问操作中给出了错误回答,该测试点将会获得 init
函数中调用交互库函数的次数,和你的程序在所有 ask
函数中调用交互库函数的次数的最大值。如果 MR
、MC
函数的调用次数,而不会计入 isempty
函数的调用次数。
数据范围
对于所有测试点,
测试点 | 特殊性质 | |||
---|---|---|---|---|
A | ||||
B | ||||
C | ||||
D | ||||
- 特殊性质 A:保证
,编号为 的点的父节点为 。 - 特殊性质 B:保证所有询问均满足
。 - 特殊性质 C:保证所有询问均满足
。 - 特殊性质 D:保证所有询问均满足
。
时间限制:3s
空间限制: