#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

typedef int OBJ_ID;
typedef int STK_ID;

class UnionFind
{
	map<OBJ_ID, OBJ_ID> lnk;
	map<OBJ_ID, int>    lnkSiz;
	map<OBJ_ID, STK_ID> stk;
	map<STK_ID, int>    stkSiz;

public:
	void link( OBJ_ID x, OBJ_ID y )
	{
		link_repr( repr(x), repr(y) );
	}

	int size( STK_ID s )
	{
		return stkSiz[s];
	}

	void alloc( OBJ_ID x, STK_ID s )
	{
		stk[x]    = s;
		lnkSiz[x] = 1;
		stkSiz[s]++;
	}

private:
	OBJ_ID repr( OBJ_ID x )
	{
		// ここでPath圧縮すると計算量が nlog(n) から n ack^-1(n) に
		while( lnk.count(x) )
			x = lnk[x];
		return x;
	}

	void link_repr( OBJ_ID x, OBJ_ID y )
	{
		if( x == y )
			return;

		// 所属スタックの情報とかをマージ
		int sx=stk[x], sy=stk[y];
		if( sx < sy ) {
			stkSiz[sy] -= lnkSiz[y];
			stkSiz[sx] += lnkSiz[y];
			stk[y] = sx;
		} else if( sx > sy ) {
			stkSiz[sx] -= lnkSiz[x];
			stkSiz[sy] += lnkSiz[x];
			stk[x] = sy;
		}

		// グループ化
		if( lnkSiz[x] < lnkSiz[y] ) {
			lnk[x] = y;
			lnkSiz[y] += lnkSiz[x];
		} else {
			lnk[y] = x;
			lnkSiz[x] += lnkSiz[y];
		}
	}
};

int main()
{
	for(int L,M,N; cin>>L,L; )
	{
		// スタックやリンクの状態を管理する変数
		STK_ID nextStackID = 1;
		OBJ_ID nextObjID   = 1;
		vector<STK_ID> stack(1, 0);
		UnionFind uf;

		// L個の命令を処理
		for(int i=0; i!=L; ++i)
		{
			string cmd; cin>>cmd;

			if( cmd == "alloc" )
				uf.alloc( nextObjID++, stack.back() );
			else if( cmd == "call" )
				stack.push_back( nextStackID++ );
			else if( cmd == "link" )
				cin >> N >> M,
				uf.link( N, M );
			else if( cmd == "return" )
				cout << uf.size(stack.back()) << endl,
				stack.pop_back();
		}
	}
}