#L2714. 「BalkanOI 2018 Day2」Popa

「BalkanOI 2018 Day2」Popa

题目描述
翻译自 BalkanOI 2018 Day2 T2「Popa」

Ghiță 有一个下标从 00 开始的正整数序列 SS。他想要构造一个节点编号为 0,1,,N10,1,\ldots ,N-1 的二叉树,满足:

  1. 树的中序遍历按节点编号升序排列;
  2. 如果 xxyy 节点的父亲,那么 SxS_x 整除 SyS_y

序列 SS 被 Andrii Popa 偷走了,但 Ghiță 可以对任意两个连续子序列 [a,b][a,b][c,d][c,d] 询问 gcd[a,b]\gcd[a,b] 是否等于 gcd[c,d]\gcd[c,d],其中 gcd[x,y]\gcd[x,y]Sx,Sx+1,Sx+2,,SyS_x,S_{x+1},S_{x+2},\ldots ,S_y 的最大公因数。

他最多只能使用 QQ 次询问,请帮他在不超过限制的情况下构建出二叉树。保证这是可能的。


交互方式
本题只支持 C++ 语言使用函数交互,其他语言可以通过 IO 交互来完成本题。

选手应包含头文件 popa.h。选手需实现如下函数:

int solve(int N, int* Left, int* Right);

函数需返回树的根节点,并且将 Left[i]Right[i] 分别赋值为 ii 的左子节点和右子节点。如果节点 ii 没有左子节点,则 Left[i] 应被赋为 1-1,如果节点 ii 没有右子节点,则 Right[i] 应被赋为 1-1LeftRight 分别指向两个空间已被分配好且长度恰好为 NN 的数组。

函数 solve 在一次运行中会被调用最多 55 次。

选手可以调用如下函数:

int query(int a, int b, int c, int d);

这个函数当且仅当 gcd[a,b]=gcd[c,d]\gcd[a,b]=\gcd[c,d] 时返回 11,其中 0ab<N0\le a\le b<N0cd<N0\le c\le d<N,否则返回 00


使用 IO 交互
你的程序可以使用标准输入输出与交互器交互,格式如下。

在程序的开始,你应从标准输入读取一个整数 TT,表示测试数据组数。

接下来开始进行每组数据的交互。在每组数据交互开始,你应从标准输入读取一个整数 NN,意义同题目描述。接下来,如需调用 query 函数,你的程序应先输出一个 ?,后输出四个整数 a,b,c,da,b,c,d,意义同「交互」一节中函数的四个参数。整数与 ?,整数与整数之间用一个空格分隔;如果 solve 函数返回,你的程序应先输出形如 ! r 的一行,rr 表示 solve 函数的返回值。接下来输出两行长度为 NN 的整数数列,第一行按顺序输出 Left 数组中的元素,第二行按顺序输出 Right 数组中的元素。任意两个整数之间用一个空格隔开。

请不要忘记对于每行,都要输出换行符,并刷新标准输出缓冲区。


样例
例如 S=[12,4,16,2,2,20]S=[12, 4, 16, 2, 2, 20],一组交互过程如下:

调用 solve 调用 query 调用 solve 之后
solve(6, Left, Right)
query(0, 1, 3, 5) 返回 00
query(4, 5, 1, 3) 返回 11
solve 返回值为 33
Left 指向 [1,0,1,1,1,1][-1, 0, -1, 1, -1, -1]
Right 指向 [1,2,1,4,5,1][-1, 2, -1, 4, 5, -1]

样例中,Ghiță 国王想要的树形态如下图所示。


评分

子任务编号 限制 分值
1 N=100,Q=104N=100, Q=10^4 37
2 N=103,Q=2×104N=10^3, Q=2\times 10^4 24
3 N=103,Q=2×103N=10^3, Q=2\times 10^3 39