UOJ Logo Universal Online Judge

UOJ

#615. 【JOISC2021】购物

附件下载 统计

JOI 商店售卖 N 件商品,编号从 0N1,商品 i 的价格为 Pi,商品的价格两两不同。

Anna 来到了 JOI 商店购物,他希望买编号在 LR 之间的商品中,最便宜的一件,但是她不知道商品的价格。

Anna 将与店员 Bruno 交流后决定买哪件商品,Bruno 知道每件商品的价格,但是他不知道 Anna 想要的编号区间 [L,R]

Anna 和 Bruno 将使用电子设备发送字符通信,每个字符都是 01。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 表示商品数量,LR 表示你想要的商品编号区间。

void ReceiveA(bool x);

每当 Bruno 向 Anna 发送字符时都会调用此函数。

xtrue 表示 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]

样例评测库

程序将以如下方式执行:

对于每个测试点,评测库创建两个队列 Qx,Qy,分别存储 Bruno 和 Anna 发送的字符,然后重复如下过程。

  1. 调用 InitAInitB,并将通过 SendBSendA 发送的字符对应加入队列 QxQy
  2. 如果 QxQy 均空,调用 Answer,结束评测。
  3. 弹出 QxQy 中的一个字符,对应调用 ReceiveAReceiveB,并将 SendASendB 发送的字符对应加入另一队列。
  4. 回到步骤 2。

样例评测库

输入格式

第一行三个整数 N,L,R,分别表示商品个数和 Anna 想要的商品区间。

第二行 N 个整数表示商品价格。

输出格式

若你的程序被判为 Wrong Answer,则交互库输出形如 Wrong Answer [1] 的信息。

否则交互库输出形如 Accepted: Y X,其中 YX 分别为 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

数据范围与评分标准

对于所有数据,保证 1N106,0LR<N,1PiN,ij,PiPj

Subtask 1 (1 points) N1000

Subtask 2 (9 points) N10000

Subtask 3 (90 points)  无特殊限制,程序的得分以如下方式给出:

你在这个子任务的得分是所有测试点得分的最小值。

对于某个测试点,设 T 为 Bruno 传输的字符数。

5000<T10000,你的分数是 25×10000T5000

1000<T5000,你的分数是 25+40×5000T4000

300<T1000,你的分数是 65+25×1000T700

T300,你的分数是 90

保证合法的交互过程中,两份评测库总用时不会超过 0.5s,分别占用空间不会超过 32MB

时间限制:两份程序及评测库共 2s

空间限制:两份程序及对应评测库分别 256MB