P1017

#include <bits/stdc++.h>

typedef std::tuple<int, int, int> PI3;
const int N = 100010;
int q, n;
std::set<int> vertices;
std::vector<PI3 > edges;
std::vector<int> out[N], in[N];
std::vector<int> twoout[N], twoin[N];
std::set<int> tmp;

bool haveVertex(int x) {
    return vertices.find(x) != vertices.end();
}
void add(int u, int v) {
    out[u].push_back(v);
    in[v].push_back(u);
    return;
}
void biadd(int u, int v) {
    twoout[u].push_back(v);
    twoin[u].push_back(v);
    twoout[v].push_back(u);
    twoin[v].push_back(u);
    return;
}

int main(void) {
    scanf("%d", &q);
    n = 0;
    int inpo, inpu, inpv, inpx, inpt, inps;
    for (int i = 1; i <= q; ++ i) {
        scanf("%d", &inpo);
        if (inpo == 1) {
            scanf("%d", &inpx);
            if (!haveVertex(inpx)) {
                vertices.insert(inpx);
                ++ n;
            }
            printf("%d\n", n);
        } else if (inpo == 2) {
            scanf("%d%d%d", &inpu, &inpv, &inpt);
            if (!haveVertex(inpu) || !haveVertex(inpv)) {
                continue;
            }
            edges.push_back(std::make_tuple(inpu, inpv, inpt));
            if (inpt == 0) {
                biadd(inpu, inpv);
            } else if (inpt == 1) {
                add(inpu, inpv);
            }
        } else if (inpo == 3) {
            scanf("%d", &inpx);
            int indeg = in[inpx].size() + twoin[inpx].size();
            int outdeg = out[inpx].size() + twoout[inpx].size();
            printf("%d %d\n", indeg, outdeg);
        } else if (inpo == 4) {
            scanf("%d", &inps);
            for (int j = 1; j <= inps; ++ j) {
                scanf("%d", &inpx);
                tmp.insert(inpx);
            }
            int ans = 0;
            for (auto it = tmp.begin(); it != tmp.end(); ++ it) {
                int u = (*it);
                if (!haveVertex(u)) {
                    continue;
                }
                for (int j = 0, up = out[u].size(); j < up; ++ j) {
                    int v = out[u][j];
                    if (tmp.find(v) == tmp.end()) {
                        continue;
                    }
                    ++ ans;
                }
                for (int j = 0, up = twoout[u].size(); j < up; ++ j) {
                    int v = twoout[u][j];
                    if (tmp.find(v) == tmp.end() || u > v) {
                        continue;
                    }
                    ++ ans;
                }
            }
            std::set<int> newbie;
            tmp.swap(newbie);
            printf("%d\n", ans);
        } else if (inpo == 5) {
            scanf("%d", &inps);
            for (int j = 1, up = edges.size(); j <= inps; ++ j) {
                scanf("%d", &inpx);
                if (inpx > up) {
                    continue;
                }
                -- inpx;
                tmp.insert(std::get<0>(edges[inpx]));
                tmp.insert(std::get<1>(edges[inpx]));
            }
            int ans = tmp.size();
            std::set<int> newbie;
            tmp.swap(newbie);
            printf("%d\n", ans);
        }
    }


    return 0;
}