本题缺少数据。
问题描述
小 Q 手中有一棵二叉树,它有 $n$ 个节点,编号 $1$ 至 $n$。现在,小 Q 给你出了一道难题,题目是让你将这些节点依次删除,并规定你只能删除没有父亲的节点(即删除一个节点前,必须将其祖先全部删除)。而游戏的难点在于,你并不知道这棵树的形态,只能通过以下方式向小 Q 询问,而小 Q 也会诚实地告诉你答案:
询问方式:$p$ 号点和 $q$ 号点的祖先关系。
回答有三种:$p$ 是 $q$ 的祖先;$q$ 是 $p$ 的祖先;以上皆非。
其中,祖先的定义为:一个点 $A$ 到根的简单路径上的所有点(不含 $A$)都是 $A$ 的祖先。
你需要做的,就是通过尽可能少的询问将所有点全部删除。
规则介绍
这是一道交互类型题目,要求选手使用 C++ 语言进行编程。在程序开头,我们已经为你声明了四个函数供你使用,他们分别是:
int size() //返回这棵树的节点数量n``
int type() //返回这棵树的类型(1、2、3,在数据规模中有详细介绍)
int question(int p, int q) //返回p号点和q号点的关系,若返回值为1,表示p是q的祖先,若返回值为-1,表示q是p的祖先,否则返回值为0,特别注意p和q必须为1至n的整数
void submit(x) //删除x号节点,特别注意x必须为1至n的整数
对于前三个函数,你的程序可以调用任意次。而对于第四个函数,你的程序只能调用 $n$ 次,且每个节点必须恰好被删除一次。并且,你的程序要保证每次删除的节点均为没有父亲的节点。
若你的程序满足上述要求并在规定时间内正常结束,系统会统计你的程序使用 question(int p, int q)
函数的次数记作 $yournum$,并与我们提供的五个评分参数 $a_1\geq a_2\geq a_3\geq a_4\geq a_5$ 作比较。若 $yournum \leq a_i$,则你的得分为 $i$ 分,同时满足多个取最高得分。
提示:经测试,question()函数每秒钟大约可调用 $2 \times 10^8$ 次。计算时间复杂度时请考虑此因素。
特别地,你的程序不允许进行任何输入输出操作,否则将按 $0$ 分处理。
样例程序
using namespace std;
int main()
{
if (size() == 2) //若n=2,以下算法可以通过一次询问保证正确性
{
if (question(1, 2) == 1) //询问1和2的祖先关系
{//若1是2的祖先,则先删1再删2
submit(1);
submit(2);
}
else
{//否则先删2再删1
submit(2);
submit(1);
}
}
else //若n不为2,则按1~n的顺序删,当然这就不能保证正确性了
for (int i=1; i<=size(); i++)
submit(i);
}
数据规模和约定
$n$ | 数据类型 | 所占比例 | $n$ | 数据类型 | 所占比例 |
$\leq 5\,000$ | 1 | $10\%$ | $\leq 300\,000$ | 1 | $10\%$ |
$\leq 5\,000$ | 2 | $10\%$ | $\leq 300\,000$ | 2 | $20\%$ |
$\leq 5\,000$ | 3 | $25\%$ | $\leq 100\,000$ | 3 | $25\%$ |
数据规模即int size()的返回值,表示这棵树的节点数量。
数据类型即int type()的返回值:
- 1 表示这棵树为一个“链”,准确地说每个点最多只有一个儿子;
- 2 表示这棵树为一棵满二叉树;
- 3 表示我们不知道这棵树有什么特殊形态。