大家都熟悉堆栈操作。一个堆栈一般有两种操作,
push
和
pop
。假设所有操作都是合法的并且最终堆栈为空。我们可以有很多方法记录堆栈的操作,
(
1
) 对每个
pop
操作,我们记录它之前一共有多少个
push
操作。
(2) 对每个pop操作,我们记录这个被Pop的元素曾经被压上了几个。
例如:操作push, push, pop, push, push, pop, push, pop, pop, pop
用第一种方法 记录为
2, 4, 5, 5, 5
用第二种方法 记录为
0, 0, 0, 2, 4
这两种记录方法可以互相转化,我们的问题是,给定第二种记录方法的序列,请求出第一种记录方法的序列。
Input
第一行一个整数n,表示序列的长度(0 < n <=1000000) 第二行n个整数,表示第二种方法的记录。
Output
一行,空格分隔的n个整数,表示第一种表示方法的序列。
Input示例
5 0 0 0 2 4
Output示例
2 4 5 5 5
第二种方法:指当前这个元素被push后、被pop之前,有多少个元素被pop过。即有多少个元素比它push晚但pop早的。
规律题。当那个数x为0是表示push和pop连着的,当那个数x不为0是表示这个数的push和pop中间有x个push或pop。
b[i] = 1 (x=0)
b[i-x]++ (x!=0)
前缀和即是答案。
#include
int a[1000001];
int b[1000001];
int main(void)
{
int n;
while(~scanf("%d", &n))
{
int i;
for(i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
if(!a[i]) b[i] = 1;
else b[i-a[i]]++, b[i] = 0;
}
int ans = 0;
for(i =1; i < n; i++)
{
ans += b[i];
printf("%d ", ans);
}
printf("%d\n", ans+b[n]);
}
return 0;
}