JOI 商店售卖 $N$ 件商品,编号从 $0$ 到 $N-1$,商品 $i$ 的价格为 $P_i$,商品的价格两两不同。
Anna 来到了 JOI 商店购物,他希望买编号在 $L$ 与 $R$ 之间的商品中,最便宜的一件,但是她不知道商品的价格。
Anna 将与店员 Bruno 交流后决定买哪件商品,Bruno 知道每件商品的价格,但是他不知道 Anna 想要的编号区间 $[L,R]$。
Anna 和 Bruno 将使用电子设备发送字符通信,每个字符都是 $0$ 或 $1$。Anna 最多发送 $18$ 个字符,而 Bruno 最多发送 $10000$ 个字符,Bruno 希望发送尽可能少的字符。
Anna 将得到 $N,L,R$,Bruno 将得到 $N$ 和每件商品的价格。你需要编写程序使 Anna 能够决定需要购买的商品编号。
任务
本题仅支持符合 C++11 及以上标准的语言。
你需要提交两份源文件,分别名为 Anna.cpp
和 Bruno.cpp
。
Anna
你必须引用 Anna.h
。
你需要是实现如下过程:
void InitA(int N, int L, int R);
对于每个测试点,这个函数只会在开始时被调用一次。
$N$ 表示商品数量,$L$ 和 $R$ 表示你想要的商品编号区间。
void ReceiveA(bool x);
每当 Bruno 向 Anna 发送字符时都会调用此函数。
$x$ 为 true
表示 Bruno 发送了 $1$,否则发送了 $0$,下同。
int Answer();
当所有字符发送结束后,这个函数会被调用恰好一次。
这个函数应当返回 Anna 想要购买的物品编号。
返回值必须在 $[L,R]$ 内,否则程序将被判为 Wrong Answer [1]
。
返回的编号必须是 $[L,R]$ 中最便宜的,否则程序将被判为 Wrong Answer [2]
。
在 InitA
和 ReceiveA
的过程中,你可以调用如下函数:
void SendA(bool y);
这个函数可以给 Bruno 发送一个字符。
这个函数最多被调用 $18$ 次,否则程序将被判为 Wrong Answer [3]
。
Bruno
你必须引用 Bruno.h
。
你需要实现如下过程:
void InitB(int N, std::vector<int> P);
对于每个测试点,这个函数会在开始时被调用一次。
$N$ 表示商品个数,数组 $P$ 表示商品的价格。
void ReceiveB(bool y);
每当 Anna 向 Bruno 发送字符时都会调用此函数。
你可以调用以下函数:
void SendB(int x);
Bruno 可以通过这个函数向 Anna 发送字符。
这个函数最多被调用 $10000$ 次,否则程序将被判为 Wrong Answer [4]
。
样例评测库
程序将以如下方式执行:
对于每个测试点,评测库创建两个队列 $Q_x,Q_y$,分别存储 Bruno 和 Anna 发送的字符,然后重复如下过程。
- 调用
InitA
和InitB
,并将通过SendB
和SendA
发送的字符对应加入队列 $Q_x$ 和 $Q_y$。 - 如果 $Q_x$ 和 $Q_y$ 均空,调用
Answer
,结束评测。 - 弹出 $Q_x$ 或 $Q_y$ 中的一个字符,对应调用
ReceiveA
或ReceiveB
,并将SendA
或SendB
发送的字符对应加入另一队列。 - 回到步骤 2。
样例评测库
输入格式
第一行三个整数 $N,L,R$,分别表示商品个数和 Anna 想要的商品区间。
第二行 $N$ 个整数表示商品价格。
输出格式
若你的程序被判为 Wrong Answer
,则交互库输出形如 Wrong Answer [1]
的信息。
否则交互库输出形如 Accepted: Y X
,其中 $Y$ 和 $X$ 分别为 Anna 发送的字符数和 Bruno 发送的字符数。
样例
input
4 0 2 3 1 4 2
explanation
以下是一次合法的通信过程:
评测库调用 | Anna 或 Bruno 调用 | 返回值 |
---|---|---|
InitA(4, 0, 2) |
$~$ | $~$ |
$~$ | SendA(true) |
$~$ |
$~$ | SendA(false) |
$~$ |
InitB(4, {3, 1, 4, 2}) |
$~$ | $~$ |
ReceiveB(true) |
$~$ | $~$ |
$~$ | SendB(true) |
$~$ |
ReceiveA(true) |
$~$ | $~$ |
ReceiveB(false) |
$~$ | $~$ |
Answer() |
$~$ | $1$ |
数据范围与评分标准
对于所有数据,保证 $1\leq N\leq 10^6,0\leq L\leq R\lt N, 1\leq P_i\leq N, \forall i\neq j,P_i\neq P_j$。
$\text{Subtask 1 (1 points) }N\leq 1000$。
$\text{Subtask 2 (9 points) }N\leq 10000$。
$\text{Subtask 3 (90 points) }$ 无特殊限制,程序的得分以如下方式给出:
你在这个子任务的得分是所有测试点得分的最小值。
对于某个测试点,设 $T$ 为 Bruno 传输的字符数。
若 $5000\lt T\leq 10000$,你的分数是 $\left\lfloor 25\times\frac{10000-T}{5000}\right\rfloor$。
若 $1000\lt T\leq 5000$,你的分数是 $25+\left\lfloor 40\times\frac{5000-T}{4000}\right\rfloor$。
若 $300\lt T\leq 1000$,你的分数是 $65+\left\lfloor 25\times\frac{1000-T}{700}\right\rfloor$。
若 $T\leq 300$,你的分数是 $90$。
保证合法的交互过程中,两份评测库总用时不会超过 $0.5s$,分别占用空间不会超过 $32MB$。
时间限制:两份程序及评测库共 $\texttt{2s}$
空间限制:两份程序及对应评测库分别 $\texttt{256MB}$