// Day Created: apr 8th 2026
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#define fname "."
#define ll long long
#define fi first
#define se second
using namespace std;
int n, m;
int res[300005];
map<pair<int, int>, int> mp;
struct Queries {
char t;
int u, v;
};
struct DSU {
int par[300005], sz[300005], scc;
vector<pair<int &, int>> history;
DSU(int n) {
scc=n;
for(int i=1; i<=n; ++i) par[i]=i, sz[i]=1;
}
int find_root(int u) {
return par[u]==u?u:find_root(par[u]);
}
void join_set(int u, int v) {
u=find_root(u), v=find_root(v);
if(u==v) return;
if(sz[u]<sz[v]) swap(u, v);
history.emplace_back(sz[u], sz[u]);
history.emplace_back(par[v], par[v]);
history.emplace_back(scc, scc);
sz[u]+=sz[v], par[v]=u, --scc;
}
void rollback(int until) {
while((int)history.size()>until)
history.back().fi=history.back().se,
history.pop_back();
}
} dsu(0);
vector<Queries> tree[4*300000+5];
void update(int id, int l, int r, const int &u, const int &v, const Queries &q) {
if(l>v || r<u) return;
if(l>=u && r<=v) {
tree[id].emplace_back(q);
return;
}
update(id<<1, l, (l+r)>>1, u, v, q);
update(id<<1|1, ((l+r)>>1)+1, r, u, v, q);
}
void get(int id, int l, int r) {
int snapshot=dsu.history.size();
for(const auto &[t, u, v]:tree[id])
if(t=='+') dsu.join_set(u, v);
if(l==r)
for(const auto &[t, u, v]:tree[id])
if(t=='?') cout<<dsu.scc<<'\n';
else
get(id<<1, l, (l+r)>>1),
get(id<<1|1, ((l+r)>>1)+1, r);
dsu.rollback(snapshot);
}
main() {
if(fopen(fname"inp", "r")) {
freopen(fname"inp", "r", stdin);
freopen(fname"out", "w", stdout);
}
cin.tie(0)->sync_with_stdio(0);
cin>>n>>m;
dsu=DSU(n);
for(int i=1; i<=m; ++i) {
char t; int u, v;
cin>>t;
Queries q;
if(t!='?') {
cin>>u>>v;
q={t, u, v};
if(t=='+') mp[{u, v}]=i;
else
update(1, 1, m, mp[{u, v}], i-1, q),
mp[{u, v}]=-1;
}
else q={t, 0, 0}, update(1, 1, m, i, i, q);
}
get(1, 1, m);
}
Ly8gRGF5IENyZWF0ZWQ6IGFwciA4dGggMjAyNgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxtYXA+CgojZGVmaW5lIGZuYW1lICIuIgojZGVmaW5lIGxsIGxvbmcgbG9uZwojZGVmaW5lIGZpIGZpcnN0CiNkZWZpbmUgc2Ugc2Vjb25kCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwppbnQgbiwgbTsKaW50IHJlc1szMDAwMDVdOwoKbWFwPHBhaXI8aW50LCBpbnQ+LCBpbnQ+IG1wOwpzdHJ1Y3QgUXVlcmllcyB7CiAgICBjaGFyIHQ7CiAgICBpbnQgdSwgdjsKfTsKCnN0cnVjdCBEU1UgewogICAgaW50IHBhclszMDAwMDVdLCBzelszMDAwMDVdLCBzY2M7CiAgICB2ZWN0b3I8cGFpcjxpbnQgJiwgaW50Pj4gaGlzdG9yeTsKICAgIERTVShpbnQgbikgewogICAgICAgIHNjYz1uOwogICAgICAgIGZvcihpbnQgaT0xOyBpPD1uOyArK2kpIHBhcltpXT1pLCBzeltpXT0xOwogICAgfQogICAgCiAgICBpbnQgZmluZF9yb290KGludCB1KSB7CiAgICAgICAgcmV0dXJuIHBhclt1XT09dT91OmZpbmRfcm9vdChwYXJbdV0pOwogICAgfQoKICAgIHZvaWQgam9pbl9zZXQoaW50IHUsIGludCB2KSB7CiAgICAgICAgdT1maW5kX3Jvb3QodSksIHY9ZmluZF9yb290KHYpOwogICAgICAgIGlmKHU9PXYpIHJldHVybjsKICAgICAgICBpZihzelt1XTxzelt2XSkgc3dhcCh1LCB2KTsKICAgICAgICBoaXN0b3J5LmVtcGxhY2VfYmFjayhzelt1XSwgc3pbdV0pOwogICAgICAgIGhpc3RvcnkuZW1wbGFjZV9iYWNrKHBhclt2XSwgcGFyW3ZdKTsKICAgICAgICBoaXN0b3J5LmVtcGxhY2VfYmFjayhzY2MsIHNjYyk7CiAgICAgICAgc3pbdV0rPXN6W3ZdLCBwYXJbdl09dSwgLS1zY2M7CiAgICB9CgogICAgdm9pZCByb2xsYmFjayhpbnQgdW50aWwpIHsKICAgICAgICB3aGlsZSgoaW50KWhpc3Rvcnkuc2l6ZSgpPnVudGlsKSAKICAgICAgICAgICAgaGlzdG9yeS5iYWNrKCkuZmk9aGlzdG9yeS5iYWNrKCkuc2UsIAogICAgICAgICAgICBoaXN0b3J5LnBvcF9iYWNrKCk7CiAgICB9Cgp9IGRzdSgwKTsKCnZlY3RvcjxRdWVyaWVzPiB0cmVlWzQqMzAwMDAwKzVdOwp2b2lkIHVwZGF0ZShpbnQgaWQsIGludCBsLCBpbnQgciwgY29uc3QgaW50ICZ1LCBjb25zdCBpbnQgJnYsIGNvbnN0IFF1ZXJpZXMgJnEpIHsKICAgIGlmKGw+diB8fCByPHUpIHJldHVybjsKICAgIGlmKGw+PXUgJiYgcjw9dikgewogICAgICAgIHRyZWVbaWRdLmVtcGxhY2VfYmFjayhxKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICB1cGRhdGUoaWQ8PDEsIGwsIChsK3IpPj4xLCB1LCB2LCBxKTsKICAgIHVwZGF0ZShpZDw8MXwxLCAoKGwrcik+PjEpKzEsIHIsIHUsIHYsIHEpOwp9Cgp2b2lkIGdldChpbnQgaWQsIGludCBsLCBpbnQgcikgewogICAgaW50IHNuYXBzaG90PWRzdS5oaXN0b3J5LnNpemUoKTsKICAgIGZvcihjb25zdCBhdXRvICZbdCwgdSwgdl06dHJlZVtpZF0pIAogICAgICAgIGlmKHQ9PScrJykgZHN1LmpvaW5fc2V0KHUsIHYpOwogICAgaWYobD09cikgCiAgICAgICAgZm9yKGNvbnN0IGF1dG8gJlt0LCB1LCB2XTp0cmVlW2lkXSkgCiAgICAgICAgICAgIGlmKHQ9PSc/JykgY291dDw8ZHN1LnNjYzw8J1xuJzsKICAgIGVsc2UgCiAgICAgICAgZ2V0KGlkPDwxLCBsLCAobCtyKT4+MSksIAogICAgICAgIGdldChpZDw8MXwxLCAoKGwrcik+PjEpKzEsIHIpOwogICAgZHN1LnJvbGxiYWNrKHNuYXBzaG90KTsKfQoKbWFpbigpIHsKICAgIGlmKGZvcGVuKGZuYW1lImlucCIsICJyIikpIHsKICAgICAgICBmcmVvcGVuKGZuYW1lImlucCIsICJyIiwgc3RkaW4pOwogICAgICAgIGZyZW9wZW4oZm5hbWUib3V0IiwgInciLCBzdGRvdXQpOwogICAgfQogICAgY2luLnRpZSgwKS0+c3luY193aXRoX3N0ZGlvKDApOwogICAgY2luPj5uPj5tOwogICAgZHN1PURTVShuKTsKICAgIGZvcihpbnQgaT0xOyBpPD1tOyArK2kpIHsKICAgICAgICBjaGFyIHQ7IGludCB1LCB2OwogICAgICAgIGNpbj4+dDsKICAgICAgICBRdWVyaWVzIHE7CiAgICAgICAgaWYodCE9Jz8nKSB7CiAgICAgICAgICAgIGNpbj4+dT4+djsKICAgICAgICAgICAgcT17dCwgdSwgdn07CiAgICAgICAgICAgIGlmKHQ9PScrJykgbXBbe3UsIHZ9XT1pOwogICAgICAgICAgICBlbHNlIAogICAgICAgICAgICAgICAgdXBkYXRlKDEsIDEsIG0sIG1wW3t1LCB2fV0sIGktMSwgcSksIAogICAgICAgICAgICAgICAgbXBbe3UsIHZ9XT0tMTsKICAgICAgICB9CiAgICAgICAgZWxzZSBxPXt0LCAwLCAwfSwgdXBkYXRlKDEsIDEsIG0sIGksIGksIHEpOwogICAgfQoKICAgIGdldCgxLCAxLCBtKTsKfQ==