#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> Tree;

#define sz(x) (int)(x).size()
#define ll long long
#define ld long double
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define pii pair <int, int>
#define vi vector<int>
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define vpi vector<pair<int, int>>

#define f0r(i,a) for(int i=0;i<a;i++)
#define f1r(i,a,b) for(int i=a;i<b;i++)

void fast_io(){
    ios_base::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
}
void io(string taskname){
    string fin = taskname + ".in";
    string fout = taskname + ".out";
    const char* FIN = fin.c_str();
    const char* FOUT = fout.c_str();
    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);
    fast_io();
}
const int MAX = 1e5+5;
template<class T, int SZ> struct MaxSegTree {
    T sum[2*SZ], mn[2*SZ], lazy[2*SZ]; // set SZ to a power of 2
    void init() {
        memset (sum,0,sizeof sum);
        memset (mn,0,sizeof mn);
        memset (lazy,0,sizeof lazy);
    }
    void push(int ind, int L, int R) {
        sum[ind] += (R-L+1)*lazy[ind];
        mn[ind] += lazy[ind];
        if (L != R) lazy[2*ind] += lazy[ind], lazy[2*ind+1] += lazy[ind];
        lazy[ind] = 0;
    }
    void pull(int ind) {
        sum[ind] = sum[2*ind]+sum[2*ind+1];
        mn[ind] = max(mn[2*ind],mn[2*ind+1]);
    }
    void build() {
        for(int i = SZ-1; i>=0; i--){
            pull(i);
        }
    }

    T qsum(int lo, int hi, int ind = 1, int L = 0, int R = SZ-1) {
        push(ind,L,R);
        if (lo > R || L > hi) return 0;
        if (lo <= L && R <= hi) return sum[ind];

        int M = (L+R)/2;
        return qsum(lo,hi,2*ind,L,M) + qsum(lo,hi,2*ind+1,M+1,R);
    }

    T qmax(int lo, int hi, int ind = 1, int L = 0, int R = SZ-1) {
        push(ind,L,R);
        if (lo > R || L > hi) return 0;
        if (lo <= L && R <= hi) return mn[ind];

        int M = (L+R)/2;
        return max(qmax(lo,hi,2*ind,L,M), qmax(lo,hi,2*ind+1,M+1,R));
    }

    void upd(int lo, int hi, ll inc, int ind = 1, int L = 0, int R = SZ-1) {
        push(ind,L,R);
        if (hi < L || R < lo) return;
        if (lo <= L && R <= hi) {
            lazy[ind] = inc;
            push(ind,L,R);
            return;
        }

        int M = (L+R)/2;
        upd(lo,hi,inc,2*ind,L,M); upd(lo,hi,inc,2*ind+1,M+1,R);
        pull(ind);
    }
};
template<int SZ> struct DSU{
    int par[SZ], sz[SZ];
    void init(){
        for(int i = 0; i<SZ; i++){
            par[i] = i;
            sz[i] = 1;
        }
    }
    int get(int x){
        if(par[x] != x){
            par[x] = get(par[x]);
        }
        return par[x];
    }
    bool unite(int x, int y){
        x = get(x);
        y = get(y);
        if(x == y){
            return false;
        }
        if(sz[x] < sz[y]){
            swap(x, y);
        }
        sz[x] += sz[y];
        par[y] = x;
        return true;
    }
};
unordered_map<int, int> seg; //turns original ordering into seg tree ordering
unordered_map<int, int> comp; //finds component in dsu into the index in the forest

vector<pii> queries; //holds queries
vector<vi> forest; //forest of nodes
vector<pii> bounds;

DSU<MAX> d;
MaxSegTree<int, (1<<17)> mst;

vi adj[MAX];
int vis [MAX];
int sub [MAX];
int depth [MAX];
int id [MAX];
int isRoot[MAX];

void dfs(int src, int tree){
    sub[src] = tree;
    vis[src] = 1;
    for(int neigh: adj[src]){
        if(vis[neigh] == 0){
            if(tree == -1){
                depth[neigh] = depth[src] + 1;
                dfs(neigh, neigh);
            }
            else{
                depth[neigh] = depth[src] +1;
                dfs(neigh, tree);
            }
        }
    }
}
int main(){
    io("newbarn");
    int q;
    cin >> q;
    d.init();
    int cur = 0;//label of nodes
    f0r(i, q){
        char c;
        int p;
        cin >> c >> p;
        p--;
        if(c == 'B'){
            if(p != -2){
                d.unite(p, cur);
                adj[cur].eb(p);
                adj[p].eb(cur);
            }
            queries.eb(mp(0, cur));
            cur++;
        }
        else{
            queries.eb(mp(1, p));
        }
    }
    int n = cur; //number of nodes
    int c = 0;
    f0r(i, n){
        id[i] = -1;
    }
    forest.resize(n+5);
    f0r(i, n){
        if(id[d.get(i)] == -1){
            id[d.get(i)] = c;
            forest[c].eb(i);
            c++;
        }
        else{
            forest[id[d.get(i)]].eb(i);
        }
    }
    cur = 0;
    f0r(i, sz(forest)){
        int st = cur;
        if(sz(forest[i]) == 0){
            continue;
        }
        comp[d.get(forest[i][0])] = i;
        f0r(j, sz(forest[i])){
            seg[forest[i][j]] = cur;
            if(j == sz(forest[i]) - 1){
                bounds.eb(mp(st, cur));
            }
            cur++;
        }

    }
    f0r(i, sz(forest)){
        if(sz(forest[i]) == 0){
            continue;
        }
        if(vis[forest[i][0]] == 1){
            continue;
        }
        dfs(forest[i][0], -1);
        isRoot[forest[i][0]] = 1;
    }

    mst.init();
    f0r(i, sz(queries)){
        int type = queries[i].f;
        int p = queries[i].s;
        if(type == 0){
            if(p <0){
                continue;
            }
            int loc = sub[p];
            if(loc<0){
                continue;
            }
            int amount = mst.qmax(seg[loc], seg[loc]);
            if(amount<depth[p]){
                mst.upd(seg[loc], seg[loc], depth[p] - amount);
            }
        }
        else{
            int idx = comp[d.get(p)];
            int l = bounds[idx].f;
            int r = bounds[idx].s;
            if(isRoot[p] == 1){
                cout << mst.qmax(l, r)  << endl;
                continue;
            }
            int loc = sub[p];
            int ans = 0;
            if(seg[loc] > l){
                ans = depth[p] +  mst.qmax(l, seg[loc]-1);
            }
            if(seg[loc] <r){
                ans = max(ans, depth[p] + mst.qmax(seg[loc] + 1, r));
            }
            int chain =  max(mst.qmax(seg[loc], seg[loc]) - depth[p], depth[p]);
            cout << max(ans, chain)<< endl;
        }
    }
    return 0;
}
