比较难的一道题。

题意是求连接标记点所需最小的边集。

相当于求一个边集,恰好经过这些点,且边集最小。

我们把这些标记点按dfn序(即dfs序)排列,发现相邻两个点的距离和(加上首末两点的距离和)刚好是上述边集的二倍。

这个性质不好证,但容易观察得到。

dfn本来就是按照dfs的遍历顺序的。

下面简单证明一下:

假设T是这些点的公共lca.

那么边集一定进过T点。所以我们把T标记不会影响边集结果。

易知:T点的dfn序一定是最小的。这些点按dfn序排序后,T在首位。

然后我们以T为起点,按dfn序一次遍历这些标记点。最终回到T。

发现每条边集上的边刚好访问2次(递归一次,回溯一次)。

所以得证。

求边集和就可以用相邻dfn序点距离和表示了。

每插入一个节点x:边集和ans增加第一个小于x的点pre与x的距离,第一个大于x的点nxt与x的距离。最后减去pre与nxt的距离。

每减去一个节点x:同理。

询问输出ans即可。(注意加上首末再除以二。)

这里用set维护即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}ll ans;
set<int>s;
int dfn[M],ti;//dfs时间戳
int id[M];//时间戳对应的节点
int dep[M];
ll d[M];//深度,到根节点的距离
int f[M][20];//某个节点的 2^i 代祖先void dfs (int x,int fa)
{dfn[x]=++ti;id[ti]=x;for(int i=head[x];i;i=ee[i].nxt){int y=ee[i].to,w=ee[i].w;if(y==fa)continue;d[y]=d[x]+w;dep[y]=dep[x]+1;f[y][0]=x;dfs(y,x);}
}
void gao(int n)
{for(int i=1;i<20;i++)for(int j=1;j<=n;j++)f[j][i]=f[f[j][i-1]][i-1];
}
int lca(int x,int y)
{if(dep[x]<dep[y])swap(x,y);for(int i=19;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];if(x==y)return x;for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
ll dis(int x,int y)
{int lc=lca(x,y);return d[x]+d[y]-d[lc]*2;
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);int n;cin>>n;for(int i=1;i<n;i++){int w,v,u;cin>>u>>v>>w;add(u,v,w);add(v,u,w);} dep[1]=1;dfs(1,0);gao(n);//for(int i=1;i<=n;i++)cout<<dfn[i]<<"   "<<i<<endl;cout<<" -------------  "<<endl;int q;cin>>q;while(q--){char op[3];cin>>op;if(op[0]=='?'){if(s.size()>=2)cout<<(dis(id[*s.begin()],id[*(--s.end())])+ans)/2<<endl;else cout<<0<<endl;}else{int x;cin>>x;if(op[0]=='+'){if(s.size()==0){s.insert(dfn[x]);continue;}auto it=s.lower_bound(dfn[x]);if(it==s.end())it--,ans+=dis(id[*it],x);else if(it==s.begin())ans+=dis(id[*it],x);else{int nxt=*it;it--;int pre=*it;ans+=dis(id[nxt],x);ans+=dis(id[pre],x);ans-=dis(id[nxt],id[pre]);}s.insert(dfn[x]);}else{auto it=s.lower_bound(dfn[x]);if(s.size()==1){s.clear();continue;}int pre,nxt;if(it==s.begin())it++,ans-=dis(id[*it],x);else {it--;pre=*it;it++;it++;if(it==s.end())ans-=dis(id[pre],x);else{nxt=*it;ans-=dis(id[pre],x);ans-=dis(id[nxt],x);ans+=dis(id[pre],id[nxt]);}}s.erase(dfn[x]);}}}return 0;
}

算法竞赛——进阶指南——acwing355. 异象石 dfn的性质+lca (简单的小证明)相关推荐

  1. 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩

    文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...

  2. 《算法竞赛进阶指南》数论篇

    <算法竞赛进阶指南>数论篇(1)-最大公约数,素数筛,欧拉函数,同余,欧拉定理,BSGS <算法竞赛进阶指南>数论篇(1)-最大公约数,素数筛,欧拉函数,同余,欧拉定理,BSG ...

  3. 《算法竞赛进阶指南(by 李煜东)》习题题解 集合

    又是笔者给自己挖的大坑. 这里是李煜东所著<算法竞赛进阶指南(by 李煜东)>的习题题解集合. 有任何错误请在对应文章下反馈或联系 nicest1919@163.com ,谢谢 qwq 从 ...

  4. CH5202 自然数拆分Lunatic版(算法竞赛进阶指南,完全背包)

    算法竞赛进阶指南,278页,完全背包 本题要点: 1.把完全背包的代码改改即可.常规的完全背包: 有n个物品,每个物品的体积是v[i], 价值是w[i], 求装到大小为m的大背包,能获得的最大价值(每 ...

  5. 中位数--《算法竞赛进阶指南》(货仓选址和七夕祭问题详解)

    中位数 今天又和大家见面了啦~ 依旧是 <算法竞赛进阶指南>的学习哦~ 中位数(Median)又称中值,统计学中的专有名词,是按顺序排列的一组数据中居于中间位置的数,代表一个样本.种群或概 ...

  6. 金字塔(算法竞赛进阶指南)

    虽然探索金字塔是极其老套的剧情,但是有一队探险家还是到了某金字塔脚下. 经过多年的研究,科学家对这座金字塔的内部结构已经有所了解. 首先,金字塔由若干房间组成,房间之间连有通道. 如果把房间看作节点, ...

  7. AcWing 122. 糖果传递【贪心】【《算法竞赛进阶指南》,微软面试题 , HAOI2008】

    AcWing 122. 糖果传递 一.题目链接 二.题目分析 (一)算法标签 (二)解题思路 三.AC代码 四.其它题解 一.题目链接 AcWing 122. 糖果传递 进阶题目 AcWing 105 ...

  8. 算法竞赛进阶指南 骑士放置

    4: 最大独立集 :选出最多的点,使得选出的点之间没有边. 求最大独立集:选出最小的点可以破坏所有的边 <==>最小点覆盖 <==>最大匹配数. 假设最大匹配数为m,共有n个点 ...

  9. 算法竞赛进阶指南 萌新入门!

    算法竞赛进阶指南 文章目录 算法竞赛进阶指南 前言 一.介绍本书 二.如何阅读本书 三.总结 **笔记思路和结构 ** 算法竞赛进阶指南 这篇文章就简单的写一下吧! 前言 ​ 作为一个想要入坑的算法的 ...

最新文章

  1. 移动机器人定位导航方式的演进
  2. box_sizing
  3. 服务器开发设计之算法宝典
  4. 217. Contains Duplicate
  5. Java——线程的四种不同形式
  6. Javascript基础之-原型(prototype)
  7. Python中jmespath解析提取json数据
  8. gcn语义分割_另辟蹊径,中科院自动化所等首次用图卷积网络解决语义分割难题...
  9. 一份清华大佬的代码模版,简洁易懂!
  10. 手工建立mysql的服务_怎样自已手工打开mysql服务
  11. erlang四大behaviour简述
  12. 数学篇--初中数学知识
  13. 如何把图纸转换为t3格式_天正cad转t3格式
  14. 达梦数据库/DM7迁移之导出sql脚本
  15. CSS过滤器(CSS filters)
  16. Word中插入集合和元素的包含符号
  17. 64位win7旗舰版java_win7 64位旗舰版下载_lenovo windows7 64位旗舰版笔记本专用系统_软件侠下载站...
  18. 利用TLF给文本加样式
  19. 死链检查工具 Xenu
  20. CSS3中steps()动画的详解

热门文章

  1. 学习之旅10-R语言介绍
  2. jadx重新打包_2.4万Star的反编译利器:Jadx
  3. [ERP]VMI概念与运用场景
  4. 两边同时取对数求复合函数_【函数与导数】复合函数求导的几个妙用
  5. 应用程序无法运行,不是有效的Win32位程序解决(新手向)
  6. php 电子图册制作,想把自己的照片做成电子相册 相册制作软件
  7. 微信小游戏接入遇到的坑
  8. IMDG中的陷阱和问题
  9. java软考真题_2016年下半年软考程序员下午真题(3)
  10. 单因子方差分析Python实现(小鸡增肥)