CSES - Shared codeLink to this code: https://cses.fi/paste/d4043165ac7615f53dd059/
#include <bits/stdc++.h>
#define up(i,a,b) for (int i = (int)a; i <= (int)b; i++)
#define pii pair<int, int>
#define all(x) x.begin(), x.end()
using namespace std;
const int maxn = 1e5 + 10;
struct Query{
int u,v;
};
struct DSU_save{
int u,v,su,sv;
};
struct DSU_rollback{
int par[maxn];
stack<DSU_save> save;
int comps;
void init(int n){
assert(save.empty());
memset(par, -1, sizeof(par[0])*(n+1));
comps = n;
}
int root(int x){
while (par[x] >= 0) x = par[x];
return x;
}
bool combinable(int u, int v){
u = root(u);
v = root(v);
if (u == v) return false;
if (par[u] > par[v]) swap(u, v);
save.push({u, v, par[u], par[v]});
--comps;
par[u] += par[v];
par[v] = u;
return true;
}
bool connected(int u, int v){
return (root(u) == root(v));
}
void rollback(){
if (save.empty()) return; //in fact: "vector<DSU_save>save" never empty
DSU_save cur = save.top();
save.pop();
++comps;
par[cur.u] = cur.su;
par[cur.v] = cur.sv;
}
};
struct Segment_Tree{
int n;
vector<vector<Query> > T;
int conn[maxn];
DSU_rollback dsu;
void init(int _n, int _q){ //be careful: number of n and q
n = _q;
T.clear();
T.resize((n << 2) + 5);
dsu.init(_n);
memset(conn, -1, sizeof(conn[0])*(n+1));
}
void add_node(int nod, int l, int r, int u, int v, const Query& Q){
if (l > v || r < u) return;
if (l >= u && r <= v){
T[nod].push_back(Q);
return;
}
int mid = (l+r) >> 1;
add_node(nod*2, l, mid, u, v, Q);
add_node(nod*2+1, mid+1, r, u, v, Q);
}
void DFS(int nod, int l, int r){
int rollcount = 0;
for (Query& Q : T[nod]){
if (dsu.combinable(Q.u, Q.v)) ++rollcount;
}
if (l == r){ //Reach the Query point
conn[l] = dsu.comps;
}
else {
int mid = (l+r) >> 1;
DFS(nod*2, l, mid);
DFS(nod*2+1, mid+1, r);
}
while (rollcount--) dsu.rollback();
}
void add_node(int l, int r, const Query& Q){
add_node(1, 1, n, l, r, Q);
}
} Tree;
int n,m,q;
vector<int> query_pos;
map<pii, int> M;
void build_tree(){
up(i,1,m){
int u,v;
cin >> u >> v;
if (u > v) swap(u, v);
M[{u, v}] = 1;
}
up(i,2,q+1){
int type,u,v;
cin >> type >> u >> v;
if (u > v) swap(u,v);
pii cur = {u, v};
if (type == 1) M[cur] = i;
else {
Tree.add_node(M[cur], i-1, {u, v});
M.erase(cur);
}
}
for (auto x : M){
int u = x.first.first;
int v = x.first.second;
Tree.add_node(x.second, q+1, {u, v});
}
}
void answer(){
up(i,1,q+1){
cout << Tree.conn[i] << " ";
}
}
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
#define Task "CONNCOMP"
if (fopen(Task".inp", "r")){
freopen(Task".inp", "r", stdin);
freopen(Task".out", "w", stdout);
}
cin >> n >> m >> q;
Tree.init(n, q+1);
build_tree();
Tree.DFS(1, 1, q+1);
answer();
}