P3250 网络 题解
Solution
单次二分:问“重要度 的所有操作,且 时间点还存在的所有操作中,是否有不经过这个点的”
整体二分:保持操作、询问按时间有序,即预先按时间排序,下传时保持有序;
对于一次 Solve,对于所有重要度 的操作(加入、删除),考虑与询问按时间混合排序,然后依次回答。
这里有比树剖更好的处理方法:树上差分,一次加入路径 就给 加一, 减一;一次询问 就查 子树和是否等于操作数,树状数组可以实现。
用不用 LCA 都是 的.
Code 1
版整体二分,未卡常
#include <bits/stdc++.h> using namespace std; #define rep(i, j, k) for (int i = (j); i <= (k); ++i) #define reo(i, j, k) for (int i = (j); i >= (k); --i) typedef long long ll; const int N = 1e5 + 10, M = 2e5 + 10; int n, m, tot, ans[N]; vector<int> G[N]; struct Item { int op, u, v, w, tim, id; }; int tim, dfn[N], dep[N], sz[N], son[N], Top[N], Fa[N]; void DFS1(int u, int fa) { sz[u] = 1, Fa[u] = fa, dep[u] = dep[fa] + 1; for (int v : G[u]) if (v != fa) { DFS1(v, u), sz[u] += sz[v]; if (sz[v] > sz[son[u]]) son[u] = v; } } void DFS2(int u, int tp) { dfn[u] = ++tim, Top[u] = tp; if (son[u]) DFS2(son[u], tp); for (int v : G[u]) if (v != Fa[u] && v != son[u]) DFS2(v, v); } int LCA(int u, int v) { while (Top[u] != Top[v]) { if (dep[Top[u]] < dep[Top[v]]) swap(u, v); u = Fa[Top[u]]; } return dep[u] < dep[v] ? u : v; } struct BIT { ll sum[N]; BIT() { memset(sum, 0, sizeof(sum)); } void Upd(int x, ll v) { for (; x <= n; x += x & -x) sum[x] += v; } ll Qry(int x) { ll res = 0; for (; x; x -= x & -x) res += sum[x]; return res; } ll Qry(int x, int y) { return Qry(y) - Qry(x - 1); } } bit; void Solve(int l, int r, vector<Item> &Op) { int cntQ = 0; for (auto it : Op) cntQ += it.op == 2; if (!cntQ) return; if (l == r) { for (auto it : Op) { if (it.op == 2) ans[it.id] = (l == 1) ? -1 : (l - 1); } return; } int mid = (l + r) >> 1; vector<Item> OpL, OpR; int cnt = 0; for (auto it : Op) { if (it.op == 0) { if (it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], 1), bit.Upd(dfn[v], 1), bit.Upd(dfn[lca], -1); if (fa) bit.Upd(dfn[fa], -1); ++cnt; } if (it.w > mid) OpR.push_back(it); else OpL.push_back(it); } if (it.op == 1) { if (it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], -1), bit.Upd(dfn[v], -1), bit.Upd(dfn[lca], 1); if (fa) bit.Upd(dfn[fa], 1); --cnt; } if (it.w > mid) OpR.push_back(it); else OpL.push_back(it); } if (it.op == 2) { int res = bit.Qry(dfn[it.u], dfn[it.u] + sz[it.u] - 1); if (res == cnt) { OpL.push_back(it); } else { OpR.push_back(it); } } } for (auto it : Op) { if (it.op == 0 && it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], -1), bit.Upd(dfn[v], -1), bit.Upd(dfn[lca], 1); if (fa) bit.Upd(dfn[fa], 1); } if (it.op == 1 && it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], 1), bit.Upd(dfn[v], 1), bit.Upd(dfn[lca], -1); if (fa) bit.Upd(dfn[fa], -1); } } Solve(l, mid, OpL), Solve(mid + 1, r, OpR); } int main() { ios::sync_with_stdio(false), cin.tie(nullptr); cin >> n >> m; rep(i, 1, n - 1) { int u, v; cin >> u >> v, G[u].push_back(v), G[v].push_back(u); } int mx = 0; vector<Item> Op(m); rep(i, 0, m - 1) { int x; cin >> Op[i].op; if (Op[i].op == 0) cin >> Op[i].u >> Op[i].v >> Op[i].w, mx = max(mx, Op[i].w); if (Op[i].op == 1) cin >> x, --x, Op[i].u = Op[x].u, Op[i].v = Op[x].v, Op[i].w = Op[x].w; if (Op[i].op == 2) cin >> Op[i].u, Op[i].id = ++tot; } DFS1(1, 0), DFS2(1, 1); Solve(1, mx + 1, Op); rep(i, 1, tot) cout << ans[i] << '\n'; return 0; }
Code 2
普通整体二分
#include <bits/stdc++.h> using namespace std; #define rep(i, j, k) for (int i = (j); i <= (k); ++i) #define reo(i, j, k) for (int i = (j); i >= (k); --i) typedef long long ll; const int N = 1e5 + 10, M = 2e5 + 10; int n, m, tot, ans[M]; vector<int> G[N]; struct Item { int op, u, v, w, tim, id; } Op[M]; int id[M], _id[M], vis[M]; int tim, dfn[N], dep[N], sz[N], son[N], Top[N], Fa[N]; void DFS1(int u, int fa) { sz[u] = 1, Fa[u] = fa, dep[u] = dep[fa] + 1; for (int v : G[u]) if (v != fa) { DFS1(v, u), sz[u] += sz[v]; if (sz[v] > sz[son[u]]) son[u] = v; } } void DFS2(int u, int tp) { dfn[u] = ++tim, Top[u] = tp; if (son[u]) DFS2(son[u], tp); for (int v : G[u]) if (v != Fa[u] && v != son[u]) DFS2(v, v); } int LCA(int u, int v) { while (Top[u] != Top[v]) { if (dep[Top[u]] < dep[Top[v]]) swap(u, v); u = Fa[Top[u]]; } return dep[u] < dep[v] ? u : v; } struct BIT { ll sum[N]; BIT() { memset(sum, 0, sizeof(sum)); } void Upd(int x, ll v) { for (; x <= n; x += x & -x) sum[x] += v; } ll Qry(int x) { ll res = 0; for (; x; x -= x & -x) res += sum[x]; return res; } ll Qry(int x, int y) { return Qry(y) - Qry(x - 1); } } bit; void Solve(int l, int r, int ql, int qr) { int cntQ = 0; rep(i, ql, qr) cntQ += Op[id[i]].op == 2; if (!cntQ) return; if (l == r) { rep(i, ql, qr) { auto it = Op[id[i]]; if (it.op == 2) ans[it.id] = (l == 1) ? -1 : (l - 1); } return; } int mid = (l + r) >> 1, cnt = 0, L = ql - 1, R; rep(i, ql, qr) { auto it = Op[id[i]]; if (it.op == 0) { if (it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], 1), bit.Upd(dfn[v], 1), bit.Upd(dfn[lca], -1); if (fa) bit.Upd(dfn[fa], -1); ++cnt; } if (it.w > mid) vis[i] = 1; else _id[++L] = id[i], vis[i] = 0; } if (it.op == 1) { if (it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], -1), bit.Upd(dfn[v], -1), bit.Upd(dfn[lca], 1); if (fa) bit.Upd(dfn[fa], 1); --cnt; } if (it.w > mid) vis[i] = 1; else _id[++L] = id[i], vis[i] = 0; } if (it.op == 2) { int res = bit.Qry(dfn[it.u], dfn[it.u] + sz[it.u] - 1); if (res == cnt) { _id[++L] = id[i], vis[i] = 0; } else { vis[i] = 1; } } } R = L; rep(i, ql, qr) if (vis[i]) _id[++R] = id[i]; rep(i, ql, qr) { auto it = Op[id[i]]; if (it.op == 0 && it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], -1), bit.Upd(dfn[v], -1), bit.Upd(dfn[lca], 1); if (fa) bit.Upd(dfn[fa], 1); } if (it.op == 1 && it.w >= mid) { int u = it.u, v = it.v, lca = LCA(u, v), fa = Fa[lca]; bit.Upd(dfn[u], 1), bit.Upd(dfn[v], 1), bit.Upd(dfn[lca], -1); if (fa) bit.Upd(dfn[fa], -1); } } rep(i, ql, qr) id[i] = _id[i]; Solve(l, mid, ql, L), Solve(mid + 1, r, L + 1, qr); } int main() { ios::sync_with_stdio(false), cin.tie(nullptr); cin >> n >> m; rep(i, 1, n - 1) { int u, v; cin >> u >> v, G[u].push_back(v), G[v].push_back(u); } int mx = 0; rep(i, 1, m) { int x; cin >> Op[i].op; if (Op[i].op == 0) cin >> Op[i].u >> Op[i].v >> Op[i].w, mx = max(mx, Op[i].w); if (Op[i].op == 1) cin >> x, Op[i].u = Op[x].u, Op[i].v = Op[x].v, Op[i].w = Op[x].w; if (Op[i].op == 2) cin >> Op[i].u, Op[i].id = ++tot; id[i] = i; } DFS1(1, 0), DFS2(1, 1), Solve(1, mx + 1, 1, m); rep(i, 1, tot) cout << ans[i] << '\n'; return 0; }
本文作者:Laijinyi
本文链接:https://www.cnblogs.com/laijinyi/p/18449769
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步