USACO 2010 Open Silver 3.Time Travel 链表?

Description
Farmer John has purchased an Acme Time Machine. He can now travel forward in time normally (without using the machine) or else jump back to an arbitrary point in the past, at which point time will start to go forward again, but potentially with events unfolding in a new, different way. FJ can never travel forward in time in his time machine.

FJ wants to raise the best possible cow herd, so he is going to try several different ideas, keeping track of various statistics of his cow herd through different possible time and event paths.

One statistic FJ cares about is the ID number of the cow he has had for the shortest period of time. Please help him out by writing a program to keep track of his herd and, after each command, reporting the ID of the most recently acquired cow of the cows he owns (or -1 if he has no cows).

FJ has a set of N (1 <= N <= 80,000) queries Q_i, conveniently numbered 1..N, which represent consecutive updates from the point of view of FJ's personal timeline.

Each query is a single line of input. The line begins with a single character c (one of 'a', 's', or 't'). If c = 'a' or c = 't', then c is followed by a space and an integer K (1 <= K <= 1,000,000).

  * If c = 'a', then FJ acquires a cow with ID K; add the cow to the herd.

  * If c = 's', then FJ sold his most recently acquired cow (it is guaranteed that FJ will have at least one cow whenever this type of query appears); remove the cow from the herd.

  * If c = 't', then FJ traveled back in time to just before the Kth query. Note that this means that FJ can potentially travel between parallel time paths (see sample input for clarification). Revert to the herd that was present just before query K.

By way of example, consider a series of 12 queries, shown below along with the cow name list and the resulting output for each query.

    Q#   Query   Owned Cows    Output      Comments
     1   a 5  -> [5]        => 5        Add a new cow with ID 5
     2   a 3  -> [5,3]      => 3        Add a new cow with ID 3
     3   a 7  -> [5,3,7]    => 7        Add a new cow with ID 7
     4   s    -> [5,3]      => 3        Sell recent cow 7
     5   t 2  -> [5]        => 5        Revert time to before query 2
     6   a 2  -> [5,2]      => 2        Add a new cow with ID 2
     7   t 4  -> [5,3,7]    => 7        Revert time to before query 4
     8   a 4  -> [5,3,7,4]  => 4        Add a new cow with ID 4
     9   s    -> [5,3,7]    => 7        Sell recent cow 4
    10   t 7  -> [5,2]      => 2        Revert time to before query 7
    11   s    -> [5]        => 5        Sell recent cow 2
    12   s    -> []         => -1       Sell recent cow 5

Input
* Line 1: A single integer: N

* Lines 2..N+1: Line i+1: query Q_i

Output
* Lines 1..N: Line i: The ID of the most recently purchased cow after query i takes effect (-1 if no cows are owned).

Sample Input
12
a 5
a 3
a 7
s
t 2
a 2
t 4
a 4
s
t 7
s
s

Sample Output
5
3
7
3
5
2
7
4
7
2
5
-1

题意:有三种操作:a向栈中加入一个数,s弹出栈顶元素,t回到某一次操作之前的状态,输出每次操作后栈顶的元素。

一开始以为是某种可持久化栈的神奇结构,结果AC掉后同学告诉我可以用一个像链表一样的东西,就是维护当前栈的栈顶和之前的一个元素就好了。

我无语了~

同学的代码:

#include <stdio.h>
int f[80010] , h[80010];
char ch[5];
int main()
{
    int n , i , t;
    scanf("%d" , &n);
    f[0] = -1;
    for(i = 1 ; i <= n ; i ++ )
    {
        scanf("%s" , ch);
        if(ch[0] == 'a')
        {
            scanf("%d" , &t);
            f[i] = t;
            h[i] = i - 1;
        }
        if(ch[0] == 't')
        {
            scanf("%d" , &t);
            f[i] = f[t - 1];
            h[i] = h[t - 1];
        }
        if(ch[0] == 's')
        {
            f[i] = f[h[i - 1]];
            h[i] = h[h[i - 1]];
        }
        printf("%d\n" , f[i]);
    }
    return 0;
}


 

我的瞎写的代码(也AC了):

#include<stdio.h>
#include<string.h>
int n;
int head[80010],next[80010],vis[80010];
int ans[80010];
char Str[5],str[80010];
int s[80010];
int sta[80010],top;
void dfs(int x)
{
	if(str[x]=='a')
	{
		sta[++top]=s[x];
	}
	if(str[x]=='s')
	{
		s[x]=sta[top];
		sta[top--]=0;
	}
	if(top)
	ans[x]=sta[top];
	else
	ans[x]=-1;
	if(x+1<=n&&str[x+1]!='t')
	dfs(x+1);
	int i;
	for(i=head[x];i!=-1;i=next[i])
	{
		dfs(i);
	}
	if(str[x]=='a')
	{
		sta[top--]=0;
	}
	if(str[x]=='s')
	{
		sta[++top]=s[x];
	}
}
int main()
{
	scanf("%d",&n);
	int i,a;
	memset(head,-1,sizeof(head));
	for(i=1;i<=n;i++)
	{
		scanf("%s",Str);
		str[i]=Str[0];
		if(Str[0]=='a')
		{
			scanf("%d",&s[i]);
		}
		if(Str[0]=='t')
		{
			scanf("%d",&a);
			next[i]=head[a-1];
			head[a-1]=i;
		}
	}
	dfs(0);
	for(i=1;i<=n;i++)
	{
		printf("%d\n",ans[i]);
	}
	return 0;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值