P1002
#include <bits/stdc++.h>
typedef long long i64;
const int N = 200010;
int q, n;
bool state[2];
struct Graph {
std::set<int> adj[N];
int edsize;
bool testedge(int u, int v) {
return adj[u].find(v) != adj[u].end();
}
void addedge(int u, int v) {
adj[u].insert(v);
adj[v].insert(u);
++ edsize;
return;
}
void remedge(int u, int v) {
adj[u].erase(adj[u].find(v));
adj[v].erase(adj[v].find(u));
-- edsize;
return;
}
void flipedge(int u, int v) {
if (testedge(u, v)) {
remedge(u, v);
} else {
addedge(u, v);
}
return;
}
};
Graph g[2];
Graph sub12, inter, sub21;
int main(void) {
int inpo, inpg, inps, inpu, inpv;
bool have[2];
scanf("%d%d", &n, &q);
i64 all = (1ll * n * (n - 1)) >> 1;
while (q --) {
scanf("%d", &inpo);
if (inpo == 1) {
scanf("%d%d", &inpg, &inps);
-- inpg;
for (int i = 0; i < inps; ++ i) {
scanf("%d%d", &inpu, &inpv);
have[0] = g[0].testedge(inpu, inpv);
have[1] = g[1].testedge(inpu, inpv);
g[inpg].flipedge(inpu, inpv);
if (inpg == 0) {
if (!have[1]) {
sub12.flipedge(inpu, inpv);
} else {
sub21.flipedge(inpu, inpv);
inter.flipedge(inpu, inpv);
}
} else {
if (!have[0]) {
sub21.flipedge(inpu, inpv);
} else {
sub12.flipedge(inpu, inpv);
inter.flipedge(inpu, inpv);
}
}
}
} else if (inpo == 2) {
scanf("%d", &inpg);
state[inpg - 1] xor_eq true;
} else if (inpo == 3) {
i64 ans0 = (state[0]) ? (all - g[0].edsize) : g[0].edsize;
i64 ans1 = (state[1]) ? (all - g[1].edsize) : g[1].edsize;
printf("%lld %lld\n", ans0, ans1);
} else if (inpo == 4) {
i64 A = sub12.edsize, B = inter.edsize, C = sub21.edsize;
i64 D = all - A - B - C;
if (!state[0]) {
if (!state[1]) {
printf("%lld %lld\n", B, A + B + C);
} else {
printf("%lld %lld\n", A, A + B + D);
}
} else {
if (!state[1]) {
printf("%lld %lld\n", C, B + C + D);
} else {
printf("%lld %lld\n", D, A + C + D);
}
}
}
}
return 0;
}