社区讨论

求助树剖样例没过,码风良好

P2542[AHOI2005] 航线规划参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@lowxjrqf
此快照首次捕获于
2023/11/13 21:18
2 年前
此快照最后确认于
2023/11/13 23:07
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
#define pb push_back
#define debug puts("debug") 
typedef long long LL;

const int N = 1e3 + 10;
const int Maxn = 1e5 + 10;

int read() {
	int res = 0, f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) f |= (ch == '-');
	for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch - '0');
	return f ? - res : res;
}
/*
先求出一颗生成树,然后把剩下的边加上,时间反演开始做就行咯。 
默认边权是 1,每次修改把非重要边变成 0,答案就是路径上的 1的个数 
*/

int n, m, cnt = 0, vis[Maxn], Kb[Maxn], dfn[Maxn], idx, siz[Maxn], top[Maxn], son[Maxn], fa[Maxn], dep[Maxn];
struct Node {int u, v;} G[Maxn]; 
struct Ques { int op, u, v, ans;} q[Maxn];
std::vector <int> E[Maxn];

inline int Find(int x) { return Kb[x] == x ? x : Kb[x] = Find(Kb[x]); }

namespace Seg {
	#define lson rt << 1
	#define rson rt << 1 | 1
	#define Mid ((l + r) >> 1)
	struct node { int l, r, Lazy, sum;} tree[Maxn * 4];
	inline void build(int rt, int l, int r) {
		tree[rt].l = l, tree[rt].r = r, tree[rt].Lazy = -1;
		if(l == r) return tree[rt].sum = 1, void();
		build(lson, l, Mid), build(rson, Mid + 1, r);
		tree[rt].sum = tree[lson].sum + tree[rson].sum;
	}
	inline void pushdown(int rt) {
		if(tree[rt].Lazy == -1) return;
		tree[lson].Lazy = tree[rt].Lazy, tree[rson].Lazy = tree[rt].Lazy;
		tree[lson].sum = 0, tree[rson].sum = 0, tree[rt].Lazy = -1;
	}
	inline void change(int rt, int l, int r) {
		if(tree[rt].l > r || tree[rt].r < l) return;
		if(tree[rt].l >= l && tree[rt].r <= r) { tree[rt].Lazy = tree[rt].sum = 0; return;}
		pushdown(rt); change(lson, l, r), change(rson, l, r);
		tree[rt].sum = tree[lson].sum + tree[rson].sum;
	}
	inline int Query(int rt, int l, int r) {
		if(tree[rt].l > r || tree[rt].r < l) return 0;
		if(tree[rt].l >= l && tree[rt].r <= r) return tree[rt].sum;
		pushdown(rt); return Query(lson, l, r) + Query(rson, l, r);
 	}
}

using namespace Seg;

namespace Cut {
	inline void dfs1(int u, int Fa) {
		fa[u] = Fa, dep[u] = dep[Fa] + 1, siz[u] = 1;
		for(int v : E[u]) {
			if(v == Fa) continue;
			dfs1(v, u);
			siz[u] += siz[v]; 
			if(siz[son[u]] < siz[v]) son[u] = v;
		}
	}
	inline void dfs2(int u, int tp) {
		dfn[u] = ++idx, top[u] = tp;
		if(son[u]) dfs2(son[u], tp);
		for(int v : E[u]) {
			if(v == fa[u] || v == son[u]) continue;
			dfs2(v, v);
		}
	}
	inline void Tree_change(int x, int y) {
		while(top[x] ^ top[y]) {
			if(dep[top[x]] < dep[top[y]]) std::swap(x, y);
			change(1, dfn[top[x]], dfn[x]);
			x = fa[top[x]];
		}
		if(dep[x] < dep[y]) std::swap(x, y);
		change(1, dfn[y] + 1, dfn[x]);
	}
	inline int Tree_Query(int x, int y) {
		int res = 0;
		while(top[x] ^ top[y]) {
			if(dep[top[x]] < dep[top[y]]) std::swap(x, y);
			res += Query(1, dfn[top[x]], dfn[x]);
			x = fa[top[x]];
		}
		if(dep[x] < dep[y]) std::swap(x, y);
		res += Query(1, dfn[y] + 1, dfn[x]);
		return res;
	}
}

using namespace Cut;

int s = 0;
 
signed main() {
	n = read(), m = read();
	for(int i = 1; i <= n; i++) Kb[i] = i;
	for(int i = 1, u, v; i <= m; i++) u = read(), v = read(), G[i] = (Node) {u, v};
	for(int i = 1; i <= m; i++) {
		int fu = Find(G[i].u), fv = Find(G[i].v);
		if(fu ^ fv) {
			if(!s) s = G[i].u;
			Kb[fu] = fv, vis[i] = 1;
			E[G[i].u].pb(G[i].v), E[G[i].v].pb(G[i].u); 
		}
	}
	while(1) {
		int op = read();
		if(op == -1) break;
		int u = read(), v = read();
		q[++cnt] = (Ques) {op, u, v, -1}; 
	}
	dfs1(s, 0), dfs2(s, 0), build(1, 1, n);
	for(int i = 1; i <= m; i++) if(!vis[i]) Tree_change(G[i].u, G[i].v);
	for(int i = cnt; i >= 1; i--) {
		if(!q[i].op) Tree_change(q[i].u, q[i].v);
		else q[i].ans = Tree_Query(q[i].u, q[i].v); 
	}
	for(int i = 1; i <= cnt; i++) if(q[i].ans != -1) printf("%d\n", q[i].ans);
	return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...