OI XXIX - kon

// https://szkopul.edu.pl/problemset/problem/TEuljz3gsotYQRUKdlEZZr1G/site/?key=statement

// Konkurs tańca towarzyskiego

#include <bits/stdc++.h>

using namespace std;

// #define int long long

constexpr int sizik = 1000 * 1001;

#define ar std::array
#define pr std::pair
#define vec std::vector

// #define GARY_DBG ;

typedef vec<vec<int>> _kra;

struct SegTree {
    std::vector<int> d;

    void build(int v, int tl, int tr) {
        if (tl == tr) {
            d[v] = 0;
        } else {
            int tm = (tl + tr) / 2;
            build(2 * v, tl, tm);
            build(2 * v + 1, tm + 1, tr);
            d[v] = d[2 * v] + d[2 * v + 1];
        }
    }

    int query(int v, int tl, int tr, int l, int r) {
        if (l > r) return 0;
        if (l == tl && r == tr) return d[v];
        int tm = (tl + tr) / 2;
        return query(v * 2, tl, tm, l, std::min(r, tm)) + query(v * 2 + 1, tm + 1, tr, std::max(l, tm + 1), r);
    }

    void update(int v, int tl, int tr, int x, int a) {
        if (tl == tr) {
            d[v] = a;
        } else {
            int tm = (tl + tr) / 2;
            if (x <= tm) {
                update(2 * v, tl, tm, x, a);
            } else {
                update(2 * v + 1, tm + 1, tr, x, a);
            }
            d[v] = d[2 * v] + d[2 * v + 1];
        }
    }

    void resize(int n) {
        d.resize(4 * n);
        build(1, 1, n);
    }

    SegTree() {}
};

int curr_max_dbg;

class Strukturka {
    std::vector<bool> dkn;
    std::vector<std::set<int>> kra;
    std::vector<std::pair<int, int>> koncowki;
    std::vector<int> rev_k;
    std::vector<std::pair<int, int>> pos;
    int last_vertex = 3;
    SegTree seg_tree;

    void bef_op() {
        koncowki.push_back({});
        kra.push_back({});
        dkn.push_back({});
        rev_k.push_back({});
        pos.push_back({});
    }

    void init_adj_list(int type) {
        for (int i = 0; i < 5; i++) {
            bef_op();
        }

        dkn[1] = type;
        dkn[2] = !type;

        kra[1].insert(2);
        // kra[2].push_back(1);
        koncowki[1] = {1, 2};
        koncowki[2] = {1, 2};
        if (dkn[1] == 1) {
            rev_k[2] = 1;
        } else {
            rev_k[2] = 2;
        }
    }

    void DFS(int v) {
        for (const auto u : kra[v]) {
            int b = rev_k[u];
            pos[b].first = (int)rep.size();
            rep.push_back(b);
            DFS(u);
            pos[b].second = (int)rep.size();
            rep.push_back(-b);
        }
    }

    int n;

public:
    std::vector<int> rep;

    void wybredny(int x, int curr) {
        bef_op();
        dkn[curr] = !dkn[x];
        int o = dkn[curr];

        if (o == 0) {
            koncowki[curr] = koncowki[x];
        } else {
            koncowki[curr] = {koncowki[x].second, last_vertex};
            kra[koncowki[x].second].insert(last_vertex);
            koncowki[x].second = last_vertex;
            rev_k[last_vertex] = curr;
            last_vertex++;
        }
    }

    void zazdrosny(int x, int curr) {
        bef_op();
        int o = dkn[curr] = dkn[x];

        if (o == 0) {
            koncowki[curr] = koncowki[x];
        } else {
            auto [v1, v2] = koncowki[x];
            kra[v1].insert(last_vertex);
            kra[v1].erase(v2);
            kra[last_vertex].insert(v2);
            koncowki[x].second = last_vertex;
            koncowki[curr] = {last_vertex, v2};
            rev_k[v2] = curr;
            rev_k[last_vertex] = x;
            last_vertex++;
        }
    }

    void run_dfs() {
        DFS(1);
        n = (int)rep.size();
        seg_tree.resize(n);

        if (dkn[1] == 1) {
            seg_tree.update(1, 1, n, pos[1].first + 1, 1);
            seg_tree.update(1, 1, n, pos[1].second + 1, -1);
        } else {
            seg_tree.update(1, 1, n, pos[2].first + 1, 1);
            seg_tree.update(1, 1, n, pos[2].second + 1, -1);
        }
    }

    int query_ans(int x) {
        if (dkn[x] == 1) return -1;

        int l, r;
        if (koncowki[x].first == 1) {
            l = 1;
        } else {
            int u1 = rev_k[koncowki[x].first];
            l = pos[u1].first + 2;
        }
        int u2 = rev_k[koncowki[x].second];
        r = pos[u2].first + 1;

        return seg_tree.query(1, 1, n, l, r);
    }

    void set_active(int x) {
        if (dkn[x] == 0) return;

        seg_tree.update(1, 1, n, pos[x].first + 1, 1);
        seg_tree.update(1, 1, n, pos[x].second + 1, -1);
    }

    Strukturka(bool type) { init_adj_list(type); }
};

int zapyt[sizik];

void solve() {
    int q;
    std::cin >> q;

    Strukturka s1(0), s2(1);
    int curr = 3;

    for (int i = 1; i <= q; i++) {
        char t;
        std::cin >> t;
        int x;
        std::cin >> x;

        zapyt[i] = -x;
        if (t == '?') zapyt[i] = x;

        if (t == 'W') {
            s1.wybredny(x, curr);
            s2.wybredny(x, curr);
            curr++;
        } else if (t == 'Z') {
            s1.zazdrosny(x, curr);
            s2.zazdrosny(x, curr);
            curr++;
        } else {
        }
    }

    curr_max_dbg = curr;

    s1.run_dfs();
    s2.run_dfs();

    curr = 3;

    for (int i = 1; i <= q; i++) {
        const int x = zapyt[i];

        if (x < 0) {
            s1.set_active(curr);
            s2.set_active(curr);
            curr++;
        } else {
            int ans = s1.query_ans(x);
            if (ans == -1) ans = s2.query_ans(x);

            std::cout << ans << '\n';
        }
    }
}

int32_t main() {
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    int t = 1;
    // std::cin >> t;

    for (; t > 0; t--) {
        solve();
    }

    return 0;
}