QOJ.ac

QOJ

Time Limit: 1.0 s Memory Limit: 256 MB Total points: 100 Unavailable

#18445. Slots

Statistics

注意:本题的测试数据可能存在问题。

游戏编程有其解决常见问题的独特技巧和窍门,这些技巧被称为“模式”(patterns)。其中一种模式与在数组中放置游戏对象有关。

有一个固定大小为 $N$ 的数组 $A$,由编号为 $1$ 到 $N$ 的插槽(slots)组成。在整个游戏过程中,游戏对象可以被创建和销毁。从创建的那一刻起,每个对象必须被分配到数组 $A$ 的一个插槽中。当一个对象被销毁时,它所占用的插槽变为空闲,并最终可以被重新用于新创建的对象。

此外,每个对象还有一个整数 ID,该 ID 在整个游戏过程中对该对象是唯一的。ID 从数字 1 开始连续分配给对象。

最后,为了确保创建新对象的时间复杂度不超过 $O(1)$,系统维护了一个包含当前所有空闲插槽的栈。

创建新对象包含以下几个步骤:

  1. 从空闲插槽栈的栈顶弹出插槽索引 $x$。
  2. 将新对象分配到插槽 $x$。
  3. 给新对象分配一个 ID,该 ID 比上一个分配的 ID 大 1;如果这是游戏中的第一个对象,则 ID 为 1。

销毁对象包含以下几个步骤:

  1. 包含被销毁对象的插槽 $x$ 变为空闲。
  2. 将插槽索引 $x$ 压入空闲插槽栈的栈顶。

这样的系统可以方便地将游戏对象放入插槽数组中。创建和销毁操作都只需要常数时间。此外,由于拥有 ID,我们甚至可以存储对对象的“弱引用”(weak references)!弱引用是一种可以用来检查其指向的对象已被销毁还是仍然存活的引用。

在本题中,你必须确定是否可以达到上述插槽系统的给定配置;如果可以,如何用最少的操作次数来实现。允许两种类型的操作:创建新对象和销毁给定插槽中的对象。

对于每个插槽,已知它在游戏结束时必须是空闲的还是被占用的。如果一个插槽必须被占用,那么其中必须包含具有指定 ID 的对象。

最初所有插槽都是空闲的,因为没有存活的对象且游戏刚刚开始。空闲插槽栈按自然顺序包含数组 $A$ 的所有插槽,其中第一个插槽(插槽 1)位于栈顶。

注意:在本题中,输入文件 input.bin 和输出文件 output.bin 包含二进制数据!所有整数均以评测机本地格式(小端序,little-endian)提供。

输入格式

输入文件由 $(N + 1)$ 个 32 位整数组成。第一个整数是 $N$ —— 插槽的数量($1 \le N \le 10^6$)。接下来的 $N$ 个数字定义了所需的配置。

每个数字定义了对应插槽的内容:

  • 0 —— 表示该插槽必须为空闲。
  • $k > 0$ —— 表示该插槽必须包含 ID 为 $k$ 的对象。

保证所有给定的 ID 互不相同且不超过 $2 \cdot 10^6$。

输出格式

如果无法获得所需的配置,输出文件必须包含一个单个的 32 位整数 -1

否则,输出 $(M + 1)$ 个 32 位整数。其中第一个整数是 $M$ —— 产生该配置所需的最少操作次数。接下来的 $M$ 个数字按执行顺序定义了具体操作。

每个操作编码为一个整数:

  • 0 —— 表示必须创建一个新对象。
  • $1 \le x \le N$ —— 表示必须销毁插槽 $x$ 中的对象。

所有操作必须是合法的:你不能销毁空闲插槽中的对象;当没有空闲插槽时,你不能创建新对象。

样例

这些样例以十六进制格式显示了输入和输出文件的内容。在测试系统中,文件将包含二进制数据。二进制格式的样例可以在题目声明旁的“News”标签页中下载。

输入样例 1

0A 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00
04 00 00 00 05 00 00 00 0A 00 00 00 09 00 00 00
08 00 00 00 00 00 00 00 0C 00 00 00

输出样例 1

0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 06 00 00 00 07 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 09 00 00 00

输入样例 2

05 00 00 00 05 00 00 00 04 00 00 00 03 00 00 00
02 00 00 00 01 00 00 00

输出样例 2

FF FF FF FF

说明

在第一个样例中,我们连续创建了 8 个对象,它们占用了前 8 个插槽,ID 分别为 1 到 8。接着,插槽 6 和 7 中的对象(ID 分别为 6 和 7)被销毁,销毁顺序使得插槽 7 最终位于空闲插槽栈的栈顶。接下来,创建了两个对象:它们被分配了接下来的 ID 9 和 10,并分别落入插槽 7 和 6 中。最后,又创建了两个对象,其 ID 分别为 11 和 12,它们被分配到最后两个插槽中,并且插槽 9 中 ID 为 11 的对象被销毁。

在第二个样例中,无法达到所需的配置。

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.