Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- using namespace __gnu_pbds;
- using namespace std;
- typedef long long ll;
- typedef unsigned long long ull;
- typedef long double ld;
- typedef pair <int, int> pii;
- typedef pair <ll, ll> pll;
- typedef tuple<int, int, int> tiii;
- typedef tuple<int, int, int, int> tiiii;
- typedef set <int> si;
- typedef map <int, int> mii;
- typedef vector <int> vi;
- typedef vector <ll> vll;
- typedef vector <vector <int>> vvi;
- typedef vector<pii> vpii;
- #define F(i, a, b) for(int i = (int)a; i <= (int)b; i++)
- #define f(i, a, b) for(int i = (int)a; i >= (int)b; i--)
- #define F2(i, a, b) for(int i = (int)a; i <= (int)b; i+=2)
- #define f2(i, a, b) for(int i = (int)a; i >= (int)b; i-=2)
- #define wh(n) int iteration = n; while(iteration--)
- #define For(t, it) for(auto it = (t).begin(); it != (t).end(); ++it)
- #define IN insert
- #define PB push_back
- #define MP make_pair
- #define MT make_tuple
- #define RS resize
- #define uset unordered_set
- #define umap unordered_map
- #define RBT tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
- ld const PI = acos(-1);
- int const N = 3e5 + 4, T = (1<<19);
- int par[N], sz[N];
- struct edge{
- int ql, qr, v, u;
- edge(){}
- edge(int a, int b, int c, int d) : ql(a), qr(b), v(c), u(d) {}
- };
- int p_dsu[2*N];
- int it_dsu = -1, cmp;
- int get_par(int v){
- while(par[v] != v)
- v = par[v];
- return v;
- }
- void unite(edge e){
- int a = get_par(e.v), b = get_par(e.u);
- if(a == b)
- return;
- if(sz[a] < sz[b])
- swap(a, b);
- p_dsu[++it_dsu] = b;
- sz[a] += sz[b];
- par[b] = a;
- cmp--;
- }
- void persist(){
- p_dsu[++it_dsu] = -1;
- }
- void restore(){
- while(it_dsu >= 0){
- int v = p_dsu[it_dsu--];
- if(v == -1)
- break;
- cmp++;
- sz[par[v]] -= sz[v];
- par[v] = v;
- }
- }
- bool need[N];
- vector<edge> gr[2*T];
- void solve(int v, int tl, int tr){
- persist();
- int tm = (tl + tr)>>1, l = v<<1, r = l|1;
- //cerr << tl << ' ' << tr << ": ";
- int gv = v|1;
- for(edge e : gr[gv]){
- if(e.ql <= tl && tr <= e.qr){
- unite(e);
- //cerr << e.v << ' ' << e.u << ", ";
- continue;
- }
- if(max(tl, e.ql) <= min(tr, e.qr))
- gr[r].PB(e);
- }
- //cerr << '\n';
- if(tl == tr){
- if(need[tl])
- cout << cmp << '\n';
- }else{
- solve(l, tl, tm);
- solve(r, tm+1, tr);
- }
- restore();
- }
- map<pii, int> was;
- //#define LOCAL
- int main(){
- ios_base::sync_with_stdio(false);
- cin.tie(NULL);
- #ifdef LOCAL
- freopen("in", "r", stdin);
- freopen("out", "w", stdout);
- #endif
- int n, m;
- cin >> n >> m;
- F(i, 1, n){
- par[i] = i;
- sz[i] = 1;
- }
- cmp = n;
- char tp;
- int a, b;
- F(i, 1, m){
- cin >> tp;
- if(tp == '?'){
- need[i] = 1;
- }else{
- cin >> a >> b;
- if(a > b)
- swap(a, b);
- if(tp == '+')
- was[MP(a, b)] = i;
- else{
- auto it = was.find(MP(a, b));
- gr[1].PB(edge(it->second, i-1, a, b));
- was.erase(it);
- }
- }
- }
- for(auto it : was)
- gr[1].PB(edge(it.second, m, it.first.first, it.first.second));
- solve(1, 1, m+1);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement