博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bzoj1969: [Ahoi2005]LANE 航线规划
阅读量:6176 次
发布时间:2019-06-21

本文共 4674 字,大约阅读时间需要 15 分钟。

题面

Sol

把询问反过来,变成加边,先加上边变成一棵树,之后每次加边就相当于去掉这两个点与这条边形成的环的代价,用树剖+线段树覆盖区间即可

# include 
# define RG register# define IL inline# define Fill(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;const int _(3e5 + 10);IL ll Read(){ RG ll x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z;}int n, fst[_], nxt[_], to[_], cnt, m, Q, ans[_], use[_];int dfn[_], Index, fa[_], size[_], top[_], son[_], deep[_];int sum[_ << 1], cov[_ << 1];struct Qry{ int c, u, v, id; IL bool operator <(RG Qry A) const{ if(c != A.c) return c < A.c; return u != A.u ? u < A.u : v < A.v; }} qry[_];struct Edge{ int u, v, flg; IL bool operator <(RG Edge A) const{ return u != A.u ? u < A.u : v < A.v; }} edge[_];IL void Add(RG int u, RG int v){ to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++; }IL int Find(RG int x){ return x == fa[x] ? x : fa[x] = Find(fa[x]); }IL void Dfs1(RG int u, RG int ff){ size[u] = 1; fa[u] = ff; deep[u] = deep[ff] + 1; for(RG int e = fst[u]; e != -1; e = nxt[e]){ if(to[e] == ff) continue; Dfs1(to[e], u); size[u] += size[to[e]]; if(size[to[e]] > size[son[u]]) son[u] = to[e]; }}IL void Dfs2(RG int u, RG int Top){ top[u] = Top; dfn[u] = ++Index; if(son[u]) Dfs2(son[u], Top); for(RG int e = fst[u]; e != -1; e = nxt[e]) if(!dfn[to[e]]) Dfs2(to[e], to[e]);}IL void Build(RG int x, RG int l, RG int r){ sum[x] = r - l + 1; if(l == r) return; RG int mid = (l + r) >> 1; Build(x << 1, l, mid); Build(x << 1 | 1, mid + 1, r);}IL void Pushdown(RG int x){ if(!cov[x]) return; cov[x << 1] = cov[x << 1 | 1] = 1; cov[x] = sum[x << 1] = sum[x << 1 | 1] = 0;}IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R){ if(L <= l && R >= r){ sum[x] = 0; cov[x] = 1; return; } RG int mid = (l + r) >> 1; Pushdown(x); if(L <= mid) Modify(x << 1, l, mid, L, R); if(R > mid) Modify(x << 1 | 1, mid + 1, r, L, R); sum[x] = sum[x << 1] + sum[x << 1 | 1];}IL int Query(RG int x, RG int l, RG int r, RG int L, RG int R){ if(L <= l && R >= r) return sum[x]; RG int mid = (l + r) >> 1, ans = 0; Pushdown(x); if(L <= mid) ans = Query(x << 1, l, mid, L, R); if(R > mid) ans += Query(x << 1 | 1, mid + 1, r, L, R); sum[x] = sum[x << 1] + sum[x << 1 | 1]; return ans;}IL void Cover(RG int u, RG int v){ while(top[u] ^ top[v]){ if(deep[top[u]] < deep[top[v]]) swap(u, v); Modify(1, 1, n, dfn[top[u]], dfn[u]); u = fa[top[u]]; } if(deep[u] > deep[v]) swap(u, v); if(u != v) Modify(1, 1, n, dfn[u] + 1, dfn[v]);}IL int Calc(RG int u, RG int v){ RG int ret = 0; while(top[u] ^ top[v]){ if(deep[top[u]] < deep[top[v]]) swap(u, v); ret += Query(1, 1, n, dfn[top[u]], dfn[u]); u = fa[top[u]]; } if(deep[u] > deep[v]) swap(u, v); if(u != v) ret += Query(1, 1, n, dfn[u] + 1, dfn[v]); return ret;}IL bool Cmp(RG Qry A, RG Qry B){ return A.id > B.id; }int main(RG int argc, RG char* argv[]){ n = Read(); m = Read(); for(RG int i = 1; i <= n; ++i) fa[i] = i, fst[i] = -1; for(RG int i = 1; i <= m; ++i){ edge[i].u = Read(), edge[i].v = Read(); if(edge[i].u > edge[i].v) swap(edge[i].u, edge[i].v); } for(RG int c = Read(); c != -1; c = Read()){ ans[++Q] = -1; qry[Q].u = Read(); qry[Q].v = Read(); qry[Q].c = c; qry[Q].id = Q; if(qry[Q].u > qry[Q].v) swap(qry[Q].u, qry[Q].v); } sort(edge + 1, edge + m + 1); sort(qry + 1, qry + Q + 1); RG int g = Q; for(RG int i = 1; i <= Q; ++i) if(qry[i].c){ g = i; break; } for(RG int l = 1, r = 1; l <= m && r <= g; ++l){ while((qry[r].u < edge[l].u || (qry[r].u == edge[l].u && qry[r].v < edge[l].v)) && r <= g) ++r; if(qry[r].u == edge[l].u && qry[r].v == edge[l].v) edge[l].flg = 1; } sort(qry + 1, qry + Q + 1, Cmp); for(RG int i = 1; i <= m; ++i){ if(edge[i].flg) continue; RG int fx = Find(edge[i].u), fy = Find(edge[i].v); if(fx == fy) continue; fa[fx] = fy; use[i] = 1; Add(edge[i].u, edge[i].v); Add(edge[i].v, edge[i].u); } Dfs1(1, 0); Dfs2(1, 1); Build(1, 1, n); for(RG int i = 1; i <= m; ++i) if(!edge[i].flg && !use[i]) Cover(edge[i].u, edge[i].v); for(RG int i = 1; i <= Q; ++i) if(qry[i].c == 0) Cover(qry[i].u, qry[i].v); else ans[qry[i].id] = Calc(qry[i].u, qry[i].v); for(RG int i = 1; i <= Q; ++i) if(ans[i] != -1) printf("%d\n", ans[i]); return 0;}

转载于:https://www.cnblogs.com/cjoieryl/p/8286513.html

你可能感兴趣的文章
5G网速真的有理论上那么高吗?
查看>>
Set添加自定义方法对象如何保证唯一性
查看>>
站在巨人肩膀上的牛顿:Kubernetes和SAP Kyma
查看>>
技术工坊|浅谈区块链的Layer2扩展(北京)
查看>>
SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
查看>>
Apache和PHP结合 及 Apache默认虚拟主机
查看>>
添加自定义监控项目配置邮件告警测试告警不发邮件的问题处理
查看>>
solidity智能合约的经典设计模式
查看>>
华为交换网络基础、基本配置、STP/RSTP
查看>>
SpringCloud 微服务 (十七) 容器部署 Docker
查看>>
不定项选择题
查看>>
netty 分析博客
查看>>
Spring Cloud构建微服务架构服务注册与发现
查看>>
BCGControlBar教程:如何将MFC控件的BCGControlBarBCGSuite添加到对话框中
查看>>
深入理解Java8 Lambda表达式
查看>>
Java集合框架面试问题集锦
查看>>
Java每天10道面试题,跟我走,offer有!(六)
查看>>
四种途径提高RabbitMQ传输数据的可靠性(二)
查看>>
c语言实现多态
查看>>
Linux 在 TOP 命令中切换内存的显示单位
查看>>