UOJ Logo Universal Online Judge

UOJ

#615. 【JOISC2021】购物

附件下载 统计

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.cppBruno.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]

InitAReceiveA 的过程中,你可以调用如下函数:

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 发送的字符,然后重复如下过程。

  1. 调用 InitAInitB,并将通过 SendBSendA 发送的字符对应加入队列 $Q_x$ 和 $Q_y$。
  2. 如果 $Q_x$ 和 $Q_y$ 均空,调用 Answer,结束评测。
  3. 弹出 $Q_x$ 或 $Q_y$ 中的一个字符,对应调用 ReceiveAReceiveB,并将 SendASendB 发送的字符对应加入另一队列。
  4. 回到步骤 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}$