P10628 [JOI Open 2024] 图书馆 3 / Library 3
题目背景
由于洛谷评测系统的限制,实际提交时,不需要引入 $\texttt{library3.h}$。你需要在代码中添加:
```cpp
void answer(std::vector);
int query(std::vector);
```
请使用 C++ 20 提交,不保证使用其他标准提交能够通过。
题目描述
几百年的时光弹指一瞬,JOI 城已然是一片废墟。IOI 酱——一个探险家,正在探索图书馆的故址。由探索结果得知:
- JOI 城的图书馆中有一个水平的书架,上面有 $N$ 个**位置**来放书,从左到右依次编号为 $0\sim N-1$。一个位置只能放一本书。
- 有 $N$ 本书放在书架上,编号为 $0\sim N-1$。
- 定义 $N$ 本书的一个**摆放**为一种将 $N$ 本书放在 $N$ 个位置上的方式。
- 存在 $N$ 本书的一个**正确摆放**,其中第 $B_i$($0\le i\le N-1$)本书放在位置 $i$ 上,其中 $B_i$ 两两不同。
书的摆放总会改变,而这个图书馆是通过不断重复以下步骤来将书还原成正确摆放的:
> **操作** 令 $x$ 是最左边的书,满足 $x$ 的位置与它在正确摆放中的位置不同。令 $y$ 为 $x$ 正确位置上的书,交换 $x,y$。
尽管 IOI 酱找到了许多旧书,她无法得知书的正确摆放。然而,她发现了一台旧机器,可以执行上面的操作。如果指定一个摆放并向机器发起询问,机器就会回答从当前摆放到正确摆放,需要重复执行多少次操作。IOI 酱想要利用这台机器,获得书的正确摆放。由于机器过于老旧,她最多只能询问 $5\, 000$ 次。
你需要写一个程序。给定书架的信息,通过最多 $5\,000$ 次询问,找出书的正确摆放。
【实现细节】
**这是一道交互题,你只需要提交一个文件(`library3.cpp`)。**
你需要在文件中引入 `library3.h`,并实现以下函数:
- `void solve(int N)`\
该函数在每个测试点中被调用恰好一次。
- 参数 $N$ 代表书的数量。
在 `library3.cpp` 中,你可以调用以下函数:
- `int query(const std::vector a)`\
IOI 酱用这个函数向机器发起询问。
- 参数 `a` 为一个长度为 $N$ 的数组,即要询问的摆放。也就是说,在指定的摆放中,第 `a[i]` 本书($0\le i\le N-1$)被放在位置 $i$。
- 返回值为一个整数,即从指定的摆放到正确摆放,需要重复执行多少次操作。
- 参数中,数组 `a` 的长度必须为 $N$。如果不满足这个条件,你的程序将被判为 **Wrong Answer[1]**。
- 参数中,数组 `a` 中的每个元素都必须在 $0$ 到 $N-1$ 之间。如果不满足这个条件,你的程序将被判为 **Wrong Answer[2]**。
- 参数中,数组 `a` 中的元素必须两两不同。如果不满足这个条件,你的程序将被判为 **Wrong Answer[3]**。
- 该函数最多只能被调用 $5\,000$ 次。如果超出调用次数,你的程序将被判为 **Wrong Answer[4]**。
- `void answer(std::vector b)`\
你的程序用这个函数回答正确摆放。
- 参数 `b` 为一个长度为 $N$ 的数组,即正确摆放。也就是说,在正确摆放中,第 `b[i]` 本书($0\le i\le N-1$)被放在位置 $i$。
- 参数中,数组 `b` 的长度必须为 $N$。如果不满足这个条件,你的程序将被判为 **Wrong Answer[5]**。
- 参数中,数组 `b` 中的每个元素都必须在 $0$ 到 $N-1$ 之间。如果不满足这个条件,你的程序将被判为 **Wrong Answer[6]**。
- 参数中,数组 `b` 中的元素必须两两不同。如果不满足这个条件,你的程序将被判为 **Wrong Answer[7]**。
- 如果你回答的摆放并不是正确摆放,你的程序将被判为 **Wrong Answer[8]**。
- 该函数必须被调用恰好一次。如果超出调用次数,你的程序将被判为 **Wrong Answer[9]**。如果未调用,你的程序将被判为 **Wrong Answer[10]**。
【注意事项】
你的程序可以定义其他函数,也可以使用全局变量。
你的程序不得使用标准输入输出流,不得以任何形式读写其他文件。但是,你的程序可以使用标准错误流来输出调试信息。
【编译运行】
可以从附件中获取 sample grader。Sample grader 即为文件 `grader.cpp`。将 `grader.cpp`,`library3.cpp`,`library3.h` 放置在同一目录下,运行以下命令即可编译你的程序。你也可以运行文件 `compile.sh` 来编译程序。
> 编译命令:`g++ -std=gnu++20 -O2 -o grader grader.cpp library3.cpp`
编译成功的话,会生成可执行文件 `grader`。注意,实际评测时用的 grader 与 sample grader 是不同的。Sample grader 会以单进程方式执行,从标准输入流中读取数据,输出结果到标准输出流。
*赛时公告:Sample grader 是非适应性的。实际评测时使用的 grader 是否适应是未知的。
输入格式
Sample grader 按照以下方式读取输入:
> $N$\
> $B_0$ $B_1$ $\cdots$ $B_{N-1}$
在正确摆放中,第 $B_i$($0\le i\le N-1$)本书放在位置 $i$ 上。
输出格式
Sample grader 会输出以下结果:
- 如果你的程序被评为正确的,返回调用 `query` 函数的次数。例如:`Accepted: 3000`。
- 否则,如果你的程序满足任一形式的错误,则按照题目描述中的错误类型输出。例如:`Wrong Answer[3]`。
如果你的程序同时满足多种错误的条件,只会输出一种错误。
说明/提示
如下是一种可能的交互过程:
| 调用 | 调用 | 返回值 |
| :--: | :--:| :--: |
| `solve(4)` | | |
| | `query([0, 1, 2, 3])` | `3` |
| | `query([1, 3, 0, 2])` | `2` |
| | `query([3, 0, 1, 2])` | `2` |
| | `query([2, 0, 3, 1])` | `0` |
| | `answer([2, 0, 3, 1])` | |
考虑调用 `query([0, 1, 2, 3])`。操作将会按照如下方式进行:
- 交换第 $0$ 本书和第 $1$ 本书的位置。于是,第 $1,0,2,3$ 本书分别被放在位置 $0,1,2,3$ 上。
- 交换第 $1$ 本书和第 $3$ 本书的位置。于是,第 $3,0,2,1$ 本书分别被放在位置 $0,1,2,3$ 上。
- 交换第 $3$ 本书和第 $2$ 本书的位置。于是,第 $2,0,3,1$ 本书分别被放在位置 $0,1,2,3$ 上。
在 $3$ 次操作后,将指定的摆放还原成了正确的摆放,所以返回值为 `3`。
样例满足所有子任务的限制条件。
### 数据范围
- $2 \le N \le 500$;
- $0 \le B_i \le N - 1$($0 \le i \le N - 1$);
- $B_i\neq B_j$($0 \le i < j \le N - 1$);
- 输入数字全为整数。
### 子任务
1. ($2 $ points)$N \le 6$;
2. ($19$ points)$N \le 100$;
3. ($79$ points)无额外约束。
由 Starrykiller 根据英文题面翻译。