P11354 [eJOI 2023] Tree Search

题目背景

本题对洛谷交互格式进行了适配,你可以在以下代码的基础上进行实现: ```cpp #include using namespace std; extern "C" bool ask(int x); extern "C" int solve(int n,vector p) { assert(ask(1)==1); return 20080520; } ```

题目描述

**这是一道交互题。** 给定一棵 $N$ 个点的有根二叉树 $T$,保证根结点的编号为 $1$。 树上恰有一个未知的结点是特殊的,你需要找出这个结点。 你每次可以向交互库询问一棵子树中是否含有特殊结点,你可以询问至多 $35$ 次。 **【实现细节】** 你需要实现下列函数: ``int solve(int N, std::vector < int > p)`` - $N$:树的结点数量。 - $p$:长度为 $N-1$ 的数组,描述树的形态。第 $i$ 个元素 $p_i$ 满足 $1\leq p_i\leq i+1$,代表编号为 $i+2$ 的结点的父亲编号。 - $p$ 中的元素两两不同。 - 你需要返回特殊结点的编号。 - 这个函数只会被调用恰好一次。 你可以调用以下函数: ``int ask(int x)`` - $x$:询问的子树根结点编号。 - 你需要保证 $1\leq x\leq N$。 - 如果子树包含特殊结点,返回值为 $1$,否则为 $0$。

输入格式

**以下为下发 grader 的输入格式,你不应该从标准输入中读入任何信息。** 第一行输入一个整数 $N$。 第二行输入 $N-1$ 个整数 $p_i$。 接下来对于每个询问,输入一个整数代表询问的返回值。

输出格式

**以下为下发 grader 的输出格式,你不应该向标准输出中打印任何信息。** 对于每个询问,输出一行 ``? x``,其中 $x$ 为询问的结点。 最后输出一行 ``! x``,其中 $x$ 为猜测的结点编号。

说明/提示

**【数据范围】** **本题采用捆绑测试。** - Subtask 1(20 pts):$N\leq 35$。 - Subtask 2(30 pts):$p_i=i+1$。 - Subtask 3(15 pts):$p_i=\frac{i}{2}+1$。 - Subtask 4(35 pts):无特殊限制。 对于 $100\%$ 的数据,保证 $1\leq N\leq 10^5$。