---
tags: codebook
---
# Time segment tree
**problem:** [TIOJ 1903](https://tioj.ck.tp.edu.tw/problems/1903)
```cpp=
constexpr int maxn = 5e5 + 5;
V<P<int>> arr[(maxn + 1) << 2];
V<int> dsu, sz;
V<tuple<int, int, int>> his;
int cnt, q;
int find(int x) {
return x == dsu[x] ? x : find(dsu[x]);
};
inline bool merge(int x, int y) {
int a = find(x), b = find(y);
if (a == b) return false;
if (sz[a] > sz[b]) swap(a, b);
his.emplace_back(a, b, sz[b]), dsu[a] = b, sz[b] += sz[a];
return true;
};
inline void undo() {
auto [a, b, s] = his.back(); his.pop_back();
dsu[a] = a, sz[b] = s;
}
#define m ((l + r) >> 1)
void insert(int ql, int qr, P<int> x, int i = 1, int l = 0, int r = q) {
// debug(ql, qr, x); return;
if (qr <= l || r <= ql) return;
if (ql <= l && r <= qr) {arr[i].push_back(x); return;}
if (qr <= m)
insert(ql, qr, x, i << 1, l, m);
else if (m <= ql)
insert(ql, qr, x, i << 1 | 1, m, r);
else {
insert(ql, qr, x, i << 1, l, m);
insert(ql, qr, x, i << 1 | 1, m, r);
}
}
void traversal(V<int>& ans, int i = 1, int l = 0, int r = q) {
int opcnt = 0;
// debug(i, l, r);
for (auto [a, b] : arr[i])
if (merge(a, b))
opcnt++, cnt--;
if (r - l == 1) ans[l] = cnt;
else {
traversal(ans, i << 1, l, m);
traversal(ans, i << 1 | 1, m, r);
}
while (opcnt--)
undo(), cnt++;
arr[i].clear();
}
#undef m
bool rit(int& ret) {
ret = 0; bool b = false; char c = cin.rdbuf()->sbumpc();
while (!isdigit(c)) {
if (c == EOF)
return false;
b = (c == '-' ? true : b);
c = cin.rdbuf()->sbumpc();
}
while (isdigit(c))
ret = ret * 10 + c - '0', c = cin.rdbuf()->sbumpc();
ret = b ? -ret : ret;
return true;
}
void wit(int x) {
if (!x) cout.rdbuf()->sputc('0');
char tmp[10]; int cnt = 0; bool b = false;
if (x & numeric_limits<int>::min())
tmp[cnt++] = -(x % 10) + '0', x /= -10, b = true;
while (x) tmp[cnt++] = x % 10 + '0', x /= 10;
if (b) cout.rdbuf()->sputc('-');
while (cnt--) cout.rdbuf()->sputc(tmp[cnt]);
}
inline void solve() {
int n, m; rit(n), rit(m), rit(q);
dsu.resize(cnt = n), sz.assign(n, 1);
iota(dsu.begin(), dsu.end(), 0);
// a, b, time, operation
UM<ll, V<int>> s;
for (int i = 0; i < m; i++) {
int a, b; rit(a), rit(b);
if (a > b) swap(a, b);
s[((ll)a << 32) | b].emplace_back(0);
}
for (int i = 0; i < q; i++) {
char c; int a, b;
cin >> c, rit(a), rit(b);
if (a > b) swap(a, b);
switch (c) {
case 'N':
s[((ll)a << 32) | b].push_back(i);
break;
case 'D':
auto tmp = s[((ll)a << 32) | b].back();
s[((ll)a << 32) | b].pop_back();
insert(tmp, i, P<int> {a, b});
}
}
for (auto [p, v] : s) {
int a = p >> 32, b = p & -1;
while (v.size()) {
insert(v.back(), q, P<int> {a, b});
v.pop_back();
}
}
V<int> ans(q);
traversal(ans);
for (auto i : ans)
wit(i), cout.rdbuf()->sputc('\n');
}
```
**problem:** [CF 813F](https://codeforces.com/contest/813/problem/F)
```cpp=
constexpr int maxn = 1e5 + 5;
V<V<int>> e;
V<P<int>> arr[(maxn + 1) << 2];
V<int> dsu, sz;
bool cur = true;
V<tuple<int, int, int>> his;
int find(int x) {return x == dsu[x] ? x : find(dsu[x]);}
bool merge(int x, int y) {
int a = find(x), b = find(y);
if (a == b) return false;
if (sz[a] > sz[b]) swap(a, b);
his.emplace_back(a, b, sz[b]);
dsu[a] = b, sz[b] += sz[a];
return true;
}
void undo() {
auto [a, b, s] = his.back();
his.pop_back();
dsu[a] = a, sz[b] = s;
}
#define m ((l + r) >> 1)
void insert(int ql, int qr, P<int> op, int i = 1, int l = 0, int r = maxn) {
if (qr <= l || r <= ql) return;
if (ql <= l && r <= qr) {arr[i].push_back(op); return;}
insert(ql, qr, op, i << 1, l, m), insert(ql, qr, op, i << 1 | 1, m, r);
}
void traversal(V<bool>& ans, int i = 1, int l = 0, int r = maxn) {
if ((int)ans.size() <= l) return;
int opcnt = 0;
for (auto [a, b] : arr[i]) {
if (find(a) == find(b))
cur = false;
else {
for (auto p : e[a])
if (merge(p, b)) opcnt++;
for (auto p : e[b])
if (merge(a, p)) opcnt++;
}
e[a].push_back(b), e[b].push_back(a);
}
if (!cur || r - l == 1) {
for (int k = l; k < r; k++)
ans[k] = cur;
} else {
traversal(ans, i << 1, l, m);
traversal(ans, i << 1 | 1, m, r);
}
cur = true;
while (opcnt--) undo();
for (auto [a, b] : arr[i])
e[a].pop_back(), e[b].pop_back();
}
#undef m
inline void solve() {
int n, q, a, b; cin >> n >> q;
e.assign(n, V<int>());
dsu.resize(n), sz.assign(n, 1);
iota(dsu.begin(), dsu.end(), 0);
UM<ll, int> m;
for (int i = 0; i < q; i++) {
cin >> a >> b, a--, b--;
if (a > b) swap(a, b);
if (m.count(((ll)a << 32) | b)) {
auto prev = m[((ll)a << 32) | b];
insert(prev, i, P<int> {a, b});
m.erase(((ll)a << 32) | b);
} else
m[((ll)a << 32) | b] = i;
}
for (auto [p, i] : m) {
int a = p >> 32, b = p & -1;
insert(i, q, P<int> {a, b});
}
V<bool> ans(q);
traversal(ans);
for (int i = 0; i < q; i++)
cout << V<string> {"NO", "YES"} [ans[i]] << endl;
}
```