线段树分治
const int N = ${1:this};int ans[N];
struct DSU { struct Info { int u, v, add; }; vector<int> p, h; vector<Info> st; int idx = 0; DSU(int n) { p.resize(n + 1); h.resize(n + 1); iota(p.begin(), p.end(), 0); }
int find(int x){ while (x != p[x]) { x = p[x]; } return p[x]; }
void merge(int u, int v){ int fu = find(u); int fv = find(v); if (fu == fv){ return; } if (h[fu] > h[fv]){ swap(fu, fv); } st.emplace_back(fu, fv, h[fu] == h[fv]); idx++; p[fu] = fv; if (h[fu] == h[fv]) { h[fv]++; } }
void restore(int t){ // 回溯到 t 时刻 while (st.size() > t){ resume(); } }
void resume() { auto [u, v, add] = st.back(); h[p[u]] -= add; p[u] = u; st.pop_back(); idx--; }} dsu(N);// 这里取决于维护的点数!
template<class Info, class Tag>struct SegmentTree { vector<Info> info; int n; SegmentTree() : n(0) { } SegmentTree(int n_) { n = n_; info.assign(4 << __lg(n), Info()); } void init(int n_) { n = n_; info.assign(4 << __lg(n), Info()); } void apply(int p, const Tag &v) { info[p].apply(v); } void range_apply(int p, int l, int r, int x, int y, const Tag &v) { if (l > y || r < x) { return; } if (l >= x && r <= y) { apply(p, v); return; } int mid = l + r >> 1; range_apply(p << 1, l, mid, x, y, v); range_apply(p << 1 | 1, mid + 1, r, x, y, v); } void range_apply(int l, int r, const Tag &v) { return range_apply(1, 1, n, l, r, v); } void range_query(int p, int l, int r) {
int pre = dsu.idx;
for (auto [u, v] : info[p].edge) {
}
// 记得不能随意 return,只要更改了,返回之前必须撤销!!!
if (l == r) {
} else { int mid = l + r >> 1; range_query(p << 1, l, mid); range_query(p << 1 | 1, mid + 1, r); }
dsu.restore(pre); }};
struct Tag { int u, v; Tag(int u, int v) : u(u), v(v) { }};
struct Info { vector<pair<int, int>> edge; Info() { edge.clear(); } void apply(const Tag &v) { edge.emplace_back(v.u, v.v); }};