社区讨论
求助树剖样例没过,码风良好
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 条回复,欢迎继续交流。
正在加载回复...