#P51408. 「2020-2021 集训队作业」lancllords

「2020-2021 集训队作业」lancllords

题目描述

这是一道交互题

相信你们已经几个月没有见过 CZL 了吧,他又回来了!我们成功地把小 U、小 Z、CZL 这三个人放在了一套题目里面。

CZL 有一副打乱的牌,这副牌从上到下有 nn 张牌(牌的位置从 00 开始编号),其中大小为 0,1,2,,n10,1,2,\dots,n-1 中的一个,且不同牌的大小互不相同。现在,你要问出这副牌里面每一张的大小,但是大魔术师怎么能够直接告诉你呢?

一开始,CZL 的左手和右手都停留在第 00 张牌的位置。每次你可以指定让它的左手向上移动一张牌,或者向下移动一张牌。你也可以让他的右手向上移动一张牌,或者向下移动一张牌。你还可以向它询问左手的牌是否比右手的牌要小。通过这些操作,你需要得到这副牌里面从上到下每一张牌的大小。

虽然 CZL 的手很灵活,但是他还要给别的人表演魔术。所以,请你在不超过 7.01087.0 \cdot 10^8 次移动内,得到这副牌从上到下每一张牌的大小。

你的代码必须包含一个头文件 "lancllords.h",你需要实现一个函数:

vector<int> answer(int n);

这个函数中正整数 nn 表示牌的个数。这个函数需要返回一个长度为 nn 的数组 PP,其中 P[i] 表示从上到下第 ii 张牌的大小。

我们假设 CZL 的左手在第 pp 张牌的位置,右手在第 qq 张牌的位置。你可以调用如下函数:

void inc_p();

表示将 CZL 的左手向下移动一张牌的位置。

void dec_p();

表示将 CZL 的左手向上移动一张牌的位置。

void inc_q();

表示将 CZL 的右手向下移动一张牌的位置。

void dec_q();

表示将 CZL 的右手向上移动一张牌的位置。

bool cmp();

表示比较第 pp 张牌的大小和第 qq 张牌的大小。若第 pp 张牌比第 qq 张牌小,则返回 true,否则返回 false

你每调用了前 44 个函数,grader 的变量 cntcnt 将增加 11。最终评测时,如果 cntcnt 的值过大,该测试点算作不通过。你需要时刻保证 0p,q<n0≤p,q<n,否则该测试点也算作不通过。

注意交互库在前四个函数调用次数不超过 7.01087.0\cdot 10^8,第五个函数调用次数不超过 10710^7 的情况下,用时不超过五秒,也就是说你的代码有至少五秒的时间。

我们下发了 [grader.cpp](file:grader.cpp)、[lancllords_sample.cpp](file:lancllords_sample.cpp) 这两个文件,其中 lancllords_sample.cpp 是一个选手代码的示例。你可以通过命令 g++ lancllords.cpp grader.cpp -o lancllords -O2 来测试你的程序。

输入格式

第一行读入一个正整数 nn,表示牌的个数。

接下来一行 nn 个数 P0,,Pn1P_0,\dots,P_{n-1},表示从上往下第 ii 张牌的大小。

输出格式

由交互库输出信息。在选手本地测试时,如果你中间 p,qp,q 的值越界了,那么会输出 "Out of bound!"。如果你返回的答案错误,会输出 "Wrong answer!",否则输出一行为 "Right Output!",另一行表示你调用前四个函数的次数。

我们下发文件中的交互库与最终交互库是不同的!但是最终的测试方式里面,排列仍然是预先生成好的,不会因你的询问而改变!

样例 1

5
3 4 0 1 2
Right Output!
You use 100 operations!

这个样例表示你调用了 100100 次前四个函数,最终得到了正确的排列。

样例 2

见下发文件中 [lancllords2.in](file:lancllords2.in)。

样例 3

见下发文件中 [lancllords3.in](file:lancllords3.in)。

子任务

对于所有数据 1n1500001≤n≤150000

Subtask 11(66 pts): n1000n≤1000

Subtask 22(77 pts): n10000n≤10000

Subtask 33(3838 pts): n30000n≤30000

Subtask 44(2525 pts): n50000n≤50000

Subtask 55(2424 pts): n150000n≤150000