CF1990E2 Catch the Mole(Hard Version)
题目描述
这是该问题的困难版本,唯一的区别在于查询次数的限制。
这是一个交互式问题。
给定一棵有 $n$ 个节点的树,节点 $1$ 为根节点。
有一只“鼹鼠”藏在某个节点上。为了找到它的位置,你可以选择一个整数 $x$($1 \le x \le n$)向评测机发起一次询问。接下来,评测机会返回 $1$,如果鼹鼠在以 $x$ 为根的子树中;否则,评测机会返回 $0$。如果评测机返回 $0$ 且鼹鼠当前不在根节点 $1$,那么鼹鼠会移动到它当前所在节点的父节点。
请在最多 $160$ 次操作内,找出鼹鼠当前所在的节点。
输入格式
每个测试包含多组测试用例。第一行包含测试用例数 $t$($1 \le t \le 100$)。接下来是每组测试用例的描述。
输出格式
每组测试用例的第一行包含一个整数 $n$($2 \le n \le 5000$)。
接下来的 $n-1$ 行描述树的边。每行包含两个用空格分隔的整数 $u_i$ 和 $v_i$($1 \le u_i, v_i \le n$),表示节点 $u_i$ 和 $v_i$ 之间有一条边。
保证输入数据构成一棵树。
本题的交互器是非自适应的。也就是说,鼹鼠最初所在的节点在每个测试用例中是固定的,在交互过程中不会改变。
你可以选择一个顶点 $x$($1 \le x \le n$)进行一次询问,输出如下格式的一行:
- "? x"
之后,你会收到:
- $0$,如果鼹鼠不在以 $x$ 为根的子树中;
- $1$,如果鼹鼠在以 $x$ 为根的子树中。
每个测试用例最多可以进行 $160$ 次此类询问。
接下来,如果你的程序已经找到了鼹鼠当前所在的节点,输出如下格式的一行:
- "! x"
注意,这一行不计入查询次数。
输出每次查询或每组测试用例的答案后,不要忘记输出换行并刷新输出缓冲区。否则会收到 Idleness Limit Exceeded 的判定。具体操作如下:
- C++:fflush(stdout) 或 cout.flush()
- Java:System.out.flush()
- Pascal:flush(output)
- Python:stdout.flush()
- 其他语言请参考相关文档。
Hack 数据
Hack 时请按照如下格式:
第一行包含测试用例数 $t$($1 \le t \le 100$)。接下来是每组测试用例的描述。
每组测试用例的第一行包含两个整数 $n$ 和 $x$($2 \le n \le 5000$,$1 \le x \le n$),分别表示树的大小和鼹鼠的初始位置。
接下来的 $n-1$ 行描述树的边。每行包含两个用空格分隔的整数 $u_i$ 和 $v_i$($1 \le u_i, v_i \le n$),表示节点 $u_i$ 和 $v_i$ 之间有一条边。
输入数据必须构成一棵树。
说明/提示
在第一个测试用例中,鼹鼠最初在节点 $2$。
对于查询 "? 2",评测机返回 $1$,因为鼹鼠在以 $2$ 为根的子树中。此时鼹鼠不会移动。
答案 $2$ 即为鼹鼠当前所在的节点,因此答案是正确的。
在第二个测试用例中,鼹鼠最初在节点 $6$。
对于查询 "? 2",评测机返回 $0$,因为鼹鼠不在以 $2$ 为根的子树中。此时鼹鼠从节点 $6$ 移动到节点 $5$。
对于查询 "? 6",评测机返回 $0$,因为鼹鼠不在以 $6$ 为根的子树中。此时鼹鼠从节点 $5$ 移动到节点 $4$。
对于查询 "? 4",评测机返回 $1$,因为鼹鼠在以 $4$ 为根的子树中。此时鼹鼠不会移动。
答案 $4$ 即为鼹鼠当前所在的节点,因此答案是正确的。
请注意,示例仅用于帮助理解题意,示例中的查询并不保证能唯一确定鼹鼠的位置。
由 ChatGPT 4.1 翻译