树剖 10 pts 求调
查看原帖
树剖 10 pts 求调
857626
_RainCappuccino_楼主2025/1/22 10:54
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
typedef pair<int, int> pi;
int n, m, q;
struct query {
	int op, u, v, ans;
}qry[N];

int h[N], etot = 1;
struct edge {
	int from, to, nxt, ans;
}e[N];
void add (int u, int v) {
	e[++ etot] = {u, v, h[u]}, h[u] = etot;
}
void clean_edge () {
	etot = 0;
	memset(h, 0, sizeof h);
}

int dfth[N], low[N], tmp;
int st[N], stack_top;
int idx, bel[N];
void tarjan (int u, int from) {
	dfth[u] = low[u] = ++ tmp;
	st[++ stack_top] = u;
	for (int i = h[u]; i; i = e[i].nxt) {
		if (i == (from ^ 1)) continue;
		int v = e[i].to;
		if (!dfth[v]) {
			tarjan(v, i), low[u] = min(low[u], low[v]);
		}
		else low[u] = min(low[u], dfth[v]);
	}
	if (low[u] == dfth[u]) {
		bel[u] = ++ idx;
		while (st[stack_top] != u) bel[st[stack_top]] = idx, stack_top --;
		stack_top --;
	}
}
void rebuild () {
	int bef = etot;
	clean_edge();
	for (int i = 2; i <= bef; i ++) {
		int u = e[i].from, v = e[i].to;
		if (bel[u] != bel[v]) {
			add (bel[u], bel[v]);
		}
	}
}
int dfn[N], to[N], fath[N], siz[N], son[N], top[N], dep[N];
int cur;
void dfs1 (int u, int fa) {
	fath[u] = fa, siz[u] = 1, dep[u] = dep[fa] + 1;
	for (int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if (v == fa) continue;
		dfs1 (v, u);
		siz[u] += siz[v];
		if (siz[v] > siz[son[u]]) son[u] = v;
	}
}
void dfs2 (int u, int tp) {
	dfn[++ cur] = u, to[cur] = u, top[u] = tp;
	if (son[u]) dfs2 (son[u], tp);
	for (int i = h[u]; i ; i = e[i].nxt) {
		int v = e[i].to;
		if (v == fath[u] || v == son[u]) continue;
		dfs2 (v, v);
	}
}
namespace t {
	int sum[N << 2], tag[N << 2];
	#define mid (l + r >> 1)
	#define ls p << 1, l, mid
	#define rs p << 1 | 1, mid + 1, r
	void pushup (int p, int l, int r) {
		sum[p] = sum[p << 1] + sum[p << 1 | 1];
	}
	void change (int p, int l, int r, int v) {
		tag[p] = v, sum[p] = v * (r - l + 1);
	}
	void pushdown (int p, int l, int r) {
		if(tag[p] != -1) change (ls, tag[p]), change(rs, tag[p]), tag[p] = -1;
	}
	void build (int p, int l, int r) {
		tag[p] = -1;
		if (l == r) sum[p] = 1;
		else build (ls), build (rs), tag[p] = 1, pushup(p, l, r);
	}
	void updata (int p, int l, int r, int ql, int qr) {
		if (ql <= l && r <= qr) {change(p, l, r, 0); return;}
		pushdown(p, l, r);
		if (mid >= ql) updata (ls, ql, qr);
		if (mid < qr) updata (rs, ql, qr);
		pushup(p, l, r);
	}
	int getsum (int p, int l, int r, int ql, int qr) {
		if (ql <= l && r <= qr) return sum[p];
		if (l > qr || r < ql) return 0;
		pushdown(p, l, r);
		return getsum(ls, ql, qr) + getsum(rs, ql, qr);
	}
};
void updata (int u, int v) {
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]]) swap(u, v);
		t::updata (1, 1, n, dfn[top[u]], dfn[u]);
		u = fath[top[u]];
	}
	if (u == v) return;
	if (dep[u] < dep[v]) swap(u, v);
	t::updata (1, 1, n, dfn[v] + 1, dfn[u]);
}
int getsum (int u, int v) {	
	int res = 0;
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]]) swap(u, v);
		res += t::getsum (1, 1, n, dfn[top[u]], dfn[u]);
		u = fath[top[u]];
	}
	if (u == v) return res;
	if (dep[u] < dep[v]) swap(u, v);
	// dep[v] < dep[u] lca = v
	res += t::getsum (1, 1, n, dfn[v] + 1, dfn[u]);
	return res;
}
pi eg[N];
map<pi, bool> mark;

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= m; i ++) {
		cin >> eg[i].first >> eg[i].second;
		if (eg[i].first > eg[i].second) swap(eg[i].first, eg[i].second);
	}
	int op, u, v;
	while (cin >> op) {
		if (op == -1) break;
		cin >> u >> v;
		qry[++ q] = {op, u, v};
		if (u > v) swap(u, v);
		if (op == 0) mark[{u, v}] = 1;
	}
	for (int i = 1; i <= m; i ++) {
		if (!mark[eg[i]]) {
			add (eg[i].first, eg[i].second);
			add (eg[i].second, eg[i].first);
		}
	}
	tarjan(1, 0);
	rebuild();
	dfs1 (1, 0);
	dfs2 (1, 1);
	t::build(1, 1, idx);
	for (int i = q; i >= 1; i --) {
		int op = qry[i].op, u = qry[i].u, v = qry[i].v;
		if (op == 0) updata (bel[u], bel[v]);
		else qry[i].ans = getsum(bel[u], bel[v]);
	}
	for (int i = 1; i <= q; i ++) {
		if (qry[i].op == 1) cout << qry[i].ans << endl;
	}
	return 0;
}
2025/1/22 10:54
加载中...