/*
给定一棵树,树上会出现宝物,也会有宝物消失
规定如果要收集树上所有宝物,就要选择一个点开始,到每个宝物点都跑一次,然后再回到那个点
现在给定m次修改,每次修改后树上就有一个宝物消失,或者一个宝物出现
请问在这次操作后,按规则跑一次找到所有宝物的最短路径长度 显然按规则跑一次找宝物经过的路径长度,就是从根节点开始dfs一次这些点再回到根节点的路径长度
那么需要将这条路径分解:
将宝物所在点按dfs序依次排列,收尾相接形成一个环
总路径就是环上相邻两点的路径之和
那么每次在环中加入一个点,只要找到环中和其dfs相邻的两个点,加入两条路径即可,删除原来的一条路径即可
每次在环中删掉一个点同理
在增删的过程中保存dfs升序,用set维护结点的dfs即可
*/
#include<bits/stdc++.h>
#include<set>
using namespace std;
#define maxn 100005
#define ll long long
struct Edge{ll to,nxt,w;}edge[maxn<<];
int head[maxn],tot,n,m;
set<int>s;//存储存在宝箱的点的dfs序
set<int>::iterator it;
int cnt,pos[maxn],id[maxn];//每个点的dfs序,dfs序对应的点
ll ans;
void init(){
memset(head,-,sizeof head);
tot=;
}
void addedge(int u,int v,int w){
edge[tot].nxt=head[u];edge[tot].w=w;edge[tot].to=v;head[u]=tot++;
}
void dfs(int u,int pre){
pos[u]=++cnt;id[cnt]=u;
for(int i=head[u];i!=-;i=edge[i].nxt){
int v=edge[i].to;
if(v!=pre)dfs(v,u);
}
} int d[maxn],f[maxn][];
ll dep[maxn];
void bfs(){
queue<int>q;
q.push();
d[]=;dep[]=;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i!=-;i=edge[i].nxt){
int v=edge[i].to;
if(d[v])continue;
d[v]=d[x]+;
dep[v]=dep[x]+edge[i].w;
f[v][]=x;
for(int k=;k<=;k++)
f[v][k]=f[f[v][k-]][k-];
q.push(v);
}
}
}
ll lca(int u,int v){
int x=u,y=v;
if(d[u]<d[v])swap(u,v);
for(int i=;i>=;i--)
if(d[f[u][i]]>=d[v])u=f[u][i];
if(u==v){
return abs(dep[x]-dep[y]);
}
for(int i=;i>=;i--)
if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
u=f[u][];
return (dep[x]+dep[y]-*dep[u]);
} int flag[maxn];
int L(int x){//返回x左边的结点
it=s.lower_bound(pos[x]);
if(it==s.begin())it=s.end();
--it;
return id[*it];
}
int R(int x){//返回x右边的结点
it=s.lower_bound(pos[x]);
++it;
if(it==s.end())it=s.begin();
return id[*it];
}
ll query(int x){
int mul,left,right;
if(flag[x]==){//往集合里加入结点
flag[x]=mul=;
s.insert(pos[x]);
left=L(x);right=R(x);
}
else {//把集合里的结点删了
flag[x]=;mul=-;
left=L(x);right=R(x);
s.erase(pos[x]);
}
if(s.size()==)return ;
ans+=(ll)mul*(lca(left,x)+lca(x,right)-lca(left,right));
return ans;
}
int main(){
init();
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
ll u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
dfs(,);//求出dfs序
bfs();//预处理
for(int i=;i<=m;i++){
int x,u,v;
scanf("%d",&x);
printf("%lld\n",query(x));
}
}

bzoj3991 lca+dfs序应用+set综合应用的更多相关文章

  1. 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)

    题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...

  2. 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  3. BZOJ3991:寻宝游戏 (LCA+dfs序+树链求并+set)

    小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走 ...

  4. BZOJ3881[Coci2015]Divljak——AC自动机+树状数组+LCA+dfs序+树链的并

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  5. nowcoder172C 保护 (倍增lca+dfs序+主席树)

    https://www.nowcoder.com/acm/contest/172/C (sbw大佬太强啦 orz) 先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径,然后就能发现,对 ...

  6. Codeforces Gym 101142 G Gangsters in Central City (lca+dfs序+树状数组+set)

    题意: 树的根节点为水源,编号为 1 .给定编号为 2, 3, 4, …, n 的点的父节点.已知只有叶子节点都是房子. 有 q 个操作,每个操作可以是下列两者之一: + v ,表示编号为 v 的房子 ...

  7. HDU 6203 ping ping ping(贪心+LCA+DFS序+BIT)

    ping ping ping Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. CH#56C(LCA+dfs序)

    题目传送门 性质是:把节点dfs序以后,异象石按这个序号排序,然后相邻两两求树上距离,这些距离的和除以二就是最小斯坦纳树. 插入删除的具体操作是根据我们上述性质,用一个set维护dfn,比如插入x,则 ...

  9. poj 2763(LCA + dfs序 +树状数组)

    算是模板题了 可以用dfs序维护点到根的距离 注意些LCA的时候遇到MAXM,要-1 #include<cstdio> #include<algorithm> #include ...

随机推荐

  1. ASP.NET MVC - 模型验证

    ASP.NET MVC - 模型验证(Model verification) 模型验证原理浅析 模型验证用到了模型绑定器.模型验证器(System.Web.Mvc.DataAnnotationsMod ...

  2. ubuntu安装和分区方案

    方案引用 Swap(相当于电脑内存):逻辑分区.大小设置为电脑内存大小,2G,4G: /boot(引导分区):主分区:大小设置为480M: /home(用户存储数据用):逻辑分区,要尽可能大,100G ...

  3. Debian9 使用 Docker 安装 gitlab完整过程

    一. 安装Docker CE (参考 官网指南) 1. 卸载老版本 sudo apt-get remove docker docker-engine docker.io  2. Update the ...

  4. Excel自动建组

    已用于测试用例自动创建组 使用要求:A列的格式如:X.X.X.X.X11.11.1.11.1.1.11.1.1.1.11.1.1.21.1.21.22 会自动将1.1.1.1.1-1.1.1.1.X组 ...

  5. k64 datasheet学习笔记3---Chip Configuration之Human machine interfaces

    1.前言 本文主要概略讲述GPIO相关的内容 2.GPIO configuration 注: GPIO模块没有访问保护,因为他没有连接到peripheral bridge slot上,不受MPU保护 ...

  6. Linux将rm命令设置为回收站【转】

    一个方案就是重定向 rm 命令以嫁接为 mv 命令,相当于给 Linux 系统定制了一个回收站. 实现方式如下: ### 重定义rm命令 ### # 定义回收站目录 trash_path='~/.tr ...

  7. C++ 类中特殊的成员变量(常变量、引用、静态)的初始化方法

    有些成员变量的数据类型比较特别,它们的初始化方式也和普通数据类型的成员变量有所不同.这些特殊的类型的成员变量包括: a.引用 b.常量 c.静态 d.静态常量(整型) e.静态常量(非整型) 常量和引 ...

  8. 【转】gcc命令中参数c和o混合使用的详解

    gcc -c a.c  编译成目标文件a.o  gcc a.c  生成执行文件a.exe  gcc -o a -c a.c    编译成目标文件a  gcc -o a  a.c    生成执行文件a. ...

  9. linux系统常用运维命令

    目录/文件处理命令 mkdir dirname         创建文件夹 mkdir -p /tmp/a/b         递归创建目录 rm -rf dirname         删除目录及内 ...

  10. Tour HDU - 3488 有向环最小权值覆盖 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=3488 给一个无源汇的,带有边权的有向图 让你找出一个最小的哈密顿回路 可以用KM算法写,但是费用流也行 思路 1 ...