#D0630. [DAY07]通过次小找最小
[DAY07]通过次小找最小
这是一道交互式题目。
题目描述
33DAI 隐藏了一个长度为 的排列 ,也就是一个包含从 到 所有整数恰好一次的数组。你的任务是找出值为 的元素所在的位置(即下标,下标从 编号)。
为了做到这一点,你可以进行一种查询。
你可以选择两个整数 和 (),并向交互器发出查询 ? l r
。
交互器会返回在数组 的子段 (也就是从第 个元素到第 个元素)中,值第二小的元素的下标。
例如,如果 , ,你查询 ? 1 5
。子段 是整个数组。其中最小的元素是 (在下标 3),第二小的元素是 (在下标 5)。所以交互器会返回 5
。你可以通过输入得到交互器的返回值。
你的目标是在不超过 次 查询内找到值为 的元素的下标。
找到答案后,你需要输出 ! k
,其中 是值为 的元素的下标。输出答案后,你的程序应立即终止。
交互格式
首先,你的程序需要从标准输入读取一个整数 。
然后,你可以开始进行查询。
要进行一次查询,请在单行('\n'
结尾)中输出 ? l r
()。然后你必须刷新输出缓冲区。之后,从标准输入读取一个整数,即查询的回答。
当你确定了值为 的元素的下标 时,输出 ! k
。然后请刷新缓冲区并终止程序。
在 C++ 中,cout
可以使用 cout.flush();
刷新,printf
可以使用 fflush(stdout);
来强制刷新缓冲区。
5
5
1
1
2
? 1 5
? 1 4
? 1 3
? 1 2
! 3
在这个例子中,隐藏的排列可能是 。
- 首先程序读入 。
? 1 5
-> 返回5
(第二小元素 的位置)? 1 4
-> 。最小值是 (下标3
),第二小是 (下标1
)。返回1
。? 1 3
-> 。最小值是 (下标3
),第二小是 (下标1
)。返回1
。? 1 2
-> 。最小值是 (下标1
),第二小是 (下标2
)。返回2
。- 通过一系列查询,程序最终确定 在下标
3
,输出! 3
。
数据规模与约定
对于 的数据,保证:。
- 子任务 1 (30 分):。
- 子任务 2 (30 分):排列 保证是 "V" 形的。也就是说,存在一个下标 (),使得 ,并且 是严格递减的, 是严格递增的。例如,如果 , 一个可能的 "V" 形排列是 。
- 子任务 3 (40 分):没有特殊限制。