#include <bits/stdc++.h>
#define ll int
#define ld long double
#define el "\n"
#define _ROOT_ int main()
#pragma GCC optimize("O2")
#define FOR(i,l,r) for(int i = l ; i <= r ; i ++)
#define FORD(i,r,l) for(int i = r ; i >= l ; i --)
#define REP(i, a ) for(int i = 0 ; i < a ; i ++ )
#define fi first
#define se second
#define M 1000000007
#define MAXN 300001
#define PI acos(-1)
#define INF (1ll<<30)
#define BLOCK_SIZE 425
#define LOG 19
#define BASE 256
#define NAME "file"
#define compare(v) sort((v).begin(), (v).end()); (v).erase(unique((v).begin(), (v).end()), (v).end());
using namespace std;
const ll MOD[] = {(ll)1e9 + 2277, (ll)1e9 + 5277, (ll)1e9 + 8277, (ll)1e9 + 9277, (ll) 1e9 + 7 };
const ll NMOD = 1;
//**Variable**//
ll n, q ;
ll scc ;
ll arr[MAXN];
ll res[MAXN] ;
map<pair<ll,ll>, stack<ll> > mp ;

//**Struct**//
struct Data {
    ll u, sz ;
};
stack<Data> his ;
struct Query {
    ll u, v, t ;

} que[MAXN];

ll lab[MAXN] ;
ll find_set(ll a ) {
    return lab[a]  < 0 ? a : find_set(lab[a]);
}
bool union_set(ll u,ll v ) {
    u = find_set(u) ;
    v = find_set(v) ;
    if(u == v ) return false ;
    if(lab[u] > lab[v] ) swap(u, v ) ;
    his.push({u, lab[u]}) ;
    his.push({v, lab[v]}) ;
    lab[u] += lab[v] ;
    lab[v] = u ;
    scc -- ;
    return true;
}
void roll_back_dsu() {
    if(his.empty() ) return ;
    Data u = his.top() ;
    his.pop() ;
    lab[u.u] = u.sz ;
    u = his.top() ;
    his.pop() ;
    lab[u.u] = u.sz ;
    scc ++ ;
}
struct Seg {
    vector<pair<ll,ll >> st[MAXN << 2 ] ;
    void update(ll id, ll l, ll r, ll u, ll v, pair<ll,ll > key  ) {
        if(u > r || v < l ) return ;
        if(u <= l && v >= r ) {
            st[id].push_back(key) ;
            return ;
        }
        ll m = l + r >> 1 ;
        update(id << 1, l, m, u, v,key ) ;
        update(id << 1 | 1, m + 1, r, u, v, key ) ;
    }

    void get(ll id, ll l, ll r  ) {
        ll cnt=  0 ;

        for(auto[u, v ] : st[id]) {
            if(union_set(u, v )) {
                cnt ++ ;
            }
        }
        if(l == r ) {
            res[l] = scc ;
            FOR(ii, 1, cnt ) roll_back_dsu() ;
            return ;
        } else {
            ll m = l + r >> 1;
            get(id << 1, l, m) ;
            get(id << 1 | 1,  m +1, r ) ;
        }
        FOR(ii, 1, cnt ) roll_back_dsu() ;
    }


} seg;
//**Function**//

void init() {
    memset(lab,  -1, sizeof lab ) ;
    cin>>n >> q ;
    scc = n ;
}

void solve() {
//    cout << " before " << endl ;
    FOR(i, 1,  q ) {

        ll  x, y ;
        char type ;
        cin >> type ;
        if(type == '?') que[i].t = 3;
        else if(type == '+') {
            cin >> x >> y ;
            if(x > y ) swap(x, y ) ;
            pair<ll,ll> key = {x, y } ;
            mp[key].push(i) ;
        } else {
            cin >> x >> y ;
            if(x > y ) swap(x, y ) ;
            pair<ll,ll> key = {x, y } ;
            ll pre = mp[key].top() ;
            seg.update(1, 0, q, pre, i, key ) ;
            mp[key].pop() ;
        }
    }
    for(auto &it : mp ) {
        while(!it.se.empty() ) {
            seg.update(1, 0, q, it.se.top(), q, it.fi ) ;
            it.se.pop() ;
        }
    }
    seg.get(1, 0, q  ) ;
    FOR(i, 1,  q ) if(que[i].t == 3 ) cout << res[i] << el ;
}

_ROOT_ {
    // freopen(NAME".inp" , "r" , stdin);
    // freopen(NAME".out" , "w", stdout) ;
//    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    srand(time(nullptr)) ;
    int t = 1; // cin >> t ;
    while(t--) {
        init();
        solve();
    }
    return (0&0);
}
