内存碎片整理
题号:NC216611
时间限制:C/C++/Rust/Pascal 1秒,其他语言2秒
空间限制:C/C++/Rust/Pascal 128 M,其他语言256 M
64bit IO Format: %lld

题目描述

在操作系统中,当一个进程执行时操作系统会给这个进程分配一段连续的内存空间,当这个进程结束执行时,这一部分内存空间会被释放掉。由于计算机的进程开始时分配内存和结束时释放内存的时间各不相同,导致了一些问题。例如内存空间上三个分配了三段连续的内存空间,用于执行三个进程,如图所示(单位是字节,白色的部分是未分配的内存):


当蓝色段的进程结束,这一段内存被释放后,100到150这一段内存就被归还系统可以重新利用,如下图所示:



然后我再分配一个需要40字节的的内存,那么会变成如下图所示:



如上图绿色和红色的被分配内存之间的未被分配的内存我们一般称之为内存碎片。

一种被称之为碎片紧凑的做法可以用于进行内存碎片整理。碎片紧凑就是指我们把一些被分配的内存平移,使得被分配的内存前后相同顺序不变首尾相接,从而达到把已被分配的内存段之间的内存碎片合成一个更大的内存碎片。将上图状态的内存进行紧凑后情况,如图所示:



现在已知内存上每个字节的内存存储的信息情况,我们假设内存上只有被占用的位置所代表的字节存的都是非0的数,未被占用的位置存的均为0(内存上可以访问的最小单位是字节)。现在我们想知道对这段内存进行碎片紧凑后,内存上信息的存储情况。由于一个字节是8位,所以每个字节最多能表示数的范围是[0,255]。

上文所描述的内存碎片整理简单来说就是,给定一个序列,将序列中的0元素全部移到数组末尾(换一个说法就是对于任意一个非0元素往前面遍历,不存在0元素),移走0元素所导致的空缺由后面的的非0元素补齐。

例如:有一个序列为[1,2,0,3,4,0,0,0],我们需要将加粗的0移动到末尾,移走后序列变成[1,2,_,3,4,0,0,0,0],接着用后面的元素补齐空缺[1,2,3,4,0,0,0,0]。

输入描述:

第一行一个数n表示为内存的长度,即有多少个字节,保证n为2的整数次幂。

接下来n个数表示内存上n个字节的存储情况。

输出描述:

一行n个数,表示进行内存碎片整理过后内存上信息的存储情况。
示例1

输入

复制
16
1 0 2 3 4 5 10 0 12 0 11 1 2 3 4 5

输出

复制
1 2 3 4 5 10 12 11 1 2 3 4 5 0 0 0

备注:

对于前20%的数据保证

对于前80%的数据保证

对于100%的数据保证