很妙的一道交互。
题意简述
一棵 $n$ 个点的有根二叉树,树中节点编号为中序遍历中的 dfs 序。其中 $n \le 100$ 。
你可以询问不超过 $300$ 次形如 $(i, l, r)$ 的问题,表示询问 $i$ 子树内编号最小值是否为 $l$ 且最大值是否为 $r$ 。
请回答每个点的父亲的编号。
主要思路
考虑按照编号从小到大尝试确定父亲。维护一个栈来存储还没有确定父亲的节点。不妨设我们已经加入到点 $x$ 。
先判断其是否在栈顶的子树中,若是则直接压入栈中;否则弹出栈顶并继续直到可压入栈中。
考虑过程中弹出的点按弹出先后为 $\langle v_m\rangle$,则弹出的点子树中的最大编号均为 $x - 1$,故 $\mathrm{fth}(v_i) = v_{i + 1}$($v_{m + 1} = x$)。
加入所有点后,若栈非空,不难发现这些点子树中最大编号均为 $n$,故也相邻两点有父子关系。
那么在此过程中如何判断 $x$ 是否在某个点 $y$ 的子树内?可以询问 $(y, l_y, x - 1)$,若返回值为假则在子树中。而 $l_y$ 显然可以在过程中更新。
于是做完,查询次数 $O(n)$,据说可以卡满。
参考代码
1 |
|