Description

​ 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达。游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。

​ 小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小B需要不断地更新数据,但是小B太懒了,不愿意自己计算,因此他向你求助。为了简化问题,我们认为最开始时所有村庄内均没有宝物

Input

​ 第一行,两个整数N、M,其中M为宝物的变动次数。

​ 接下来的N-1行,每行三个整数x、y、z,表示村庄x、y之间有一条长度为z的道路。

​ 接下来的M行,每行一个整数t,表示一个宝物变动的操作。若该操作前村庄t内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

Output

​ M行,每行一个整数,其中第i行的整数表示第i次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出0。

Sample Input

4 5

1 2 30

2 3 50

2 4 60

2

3

4

2

1

Sample Output

0

100

220

220

280

Hint

\(1 \leq N,M \leq 100000\)

对于全部的数据,\(1 \leq z \leq 10^9\)

Solution

题意就是叫你维护一棵虚树,求这棵虚树边权和的2倍,事实上,考虑利用dfs序维护,只需要维护相邻dfs序间的距离即可,利用<set>维护dfs序,增加删除的时候算一下影响的距离即可。时间复杂度\(O(n \log n)\)

Code

#include <stdio.h>
#include <set>
#define MN 100005
#define R register
#define ll long long
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
inline int read(){
R int x; R bool f; R char c;
for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
return f?-x:x;
}
int h[MN],to[MN<<1],nxt[MN<<1],en,n,v[MN<<1];ll dep[MN],nans;
int sz[MN],son[MN],fa[MN],dfn[MN],top[MN],d[MN],dn,m,re[MN];char op[MN];
std::set<int> s;bool b[MN];
inline void ins(int x,int y,int vl){to[++en]=y,nxt[en]=h[x],v[en]=vl,h[x]=en;}
inline void dfs(int u,int f,ll dis,int dd){
dep[u]=dis;fa[u]=f;sz[u]=1;d[u]=dd;
for (R int i=h[u]; i; i=nxt[i])
if (to[i]!=f){
dfs(to[i],u,dis+v[i],dd+1);sz[u]+=sz[to[i]];
if (sz[to[i]]>sz[son[u]]) son[u]=to[i];
}
}
inline void dfs(int u,int tp){
dfn[u]=++dn;re[dn]=u;top[u]=tp;if (son[u]) dfs(son[u],tp);
for (R int i=h[u]; i; i=nxt[i])
if (to[i]!=fa[u]&&to[i]!=son[u]) dfs(to[i],to[i]);
}
inline int lca(int x,int y){
while(top[x]!=top[y])
if (d[top[x]]>d[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
return d[x]<d[y]?x:y;
}
inline int Left(int x){
std::set<int>::iterator it=s.find(dfn[x]);
if (it==s.begin()) return *(--s.end());
return *(--it);
}
inline int Right(int x){
std::set<int>::iterator it=s.find(dfn[x]);++it;
if (it==s.end()) return (*s.begin());
return *it;
}
inline void upp(int x){
nans+=dep[x];s.insert(dfn[x]);
R int l=Left(x),r=Right(x);
nans-=dep[lca(re[l],x)];
nans-=dep[lca(x,re[r])];
nans+=dep[lca(re[l],re[r])];
}
inline void del(int x){
nans-=dep[x];
R int l=Left(x),r=Right(x);
nans+=dep[lca(re[l],x)];
nans+=dep[lca(x,re[r])];
nans-=dep[lca(re[l],re[r])];
s.erase(dfn[x]);
}
inline ll query(){return nans<<1;}
int main(){
n=read();m=read();for (R int i=1; i<n; ++i){
R int x=read(),y=read(),v=read();
ins(x,y,v); ins(y,x,v);
}dfs(1,0,0,1);dfs(1,1);
for (R int i=1,x; i<=m; ++i){
b[x=read()]^=1;if (b[x])upp(x);
else del(x);printf("%lld\n",query());
}return 0;
}

【BZOJ3991】【SDOI2015】寻宝游戏的更多相关文章

  1. [BZOJ3991][SDOI2015]寻宝游戏

    [BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...

  2. CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏

    异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...

  3. [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set

    寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...

  4. BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】

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

  5. bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护

    之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...

  6. bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并

    题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...

  7. 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏

    在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...

  8. bzoj3991 [SDOI2015]寻宝游戏 树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...

  9. 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set

    [BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...

  10. bzoj 3991: [SDOI2015]寻宝游戏 虚树 set

    目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...

随机推荐

  1. 项目Alpha冲刺Day1

    一.会议照片 二.项目进展 1.今日安排 讨论完成项目的详细设计,并完成数据库的设计,学习powerDesigner的使用 2.问题困难 powerDesigner导出sql语句因为问题无法导入,特别 ...

  2. C语言--第三周作业

    一.PTA作业中4个题目 1.7-9 A乘以B 要求:输入的两个整数:A是你学号前两位数字,B是你学号后两位数字 a.代码 #include <stdio.h> int main () { ...

  3. MySql数据库的常用命令

    1.连接Mysql 连接本地的mysql数据库 :   mysql -u root -p    (回车之后会提示输入密码) 连接远程主机的mysql数据库 : 假设远程主机的IP为:110.110.1 ...

  4. bzoj千题计划165:bzoj5127: 数据校验

    http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf 区间的任意一个子区间都满足值域连续 等价于 区间任意一个长为2的子区间都满足值域连续 ...

  5. Mybatis学习日志

    在Mybatis深入学习的一周中,总感觉跟着师傅的视屏讲解什么都能懂,但实际自己操作的时候才发现自己一脸懵逼,不知道从何入手.但还好自己做了点笔记.在此记录一下自己浅度学习Mybatis遇到几个小问题 ...

  6. 剑指offer-两个链表的第一个公共节点

    题目描述 输入两个链表,找出它们的第一个公共结点. 解题思路 分析可得如果两个链表有公共节点,那么公共节点出现在两个链表的尾部,即从某一节点开始,两链表之后的节点全部相等.可以首先遍历两个链表得出各自 ...

  7. JQ 上传文件(单个,多个,分片)

    最原始的方式: 前端代码: <div> <span>最原始的方式</span><br /> <span>条件1:必须是 post 方式< ...

  8. java基础复习(1)

    用记事本写java文件 打开记事本,编写java文件,需要注意文件名与类名要相同 注意文件的后缀名(也叫拓展名)改为.java java对大小写是敏感的 public class nihao{\ pu ...

  9. plsql启动提示监听服务无法连接

    话说现在用的oracle少了,本人菜鸟一个,但是我真心的没有感觉到它用的少了,今天入了一个新项目,数据库使用的还是oracle,经理二话不说的给了一些东西,说了让一句你把环境啥地 配置一下,然后走人了 ...

  10. emqtt 试用(二)验证 emq 和 mosquito 的共享订阅

    本地订阅(Local Subscription) 本地订阅(Local Subscription)只在本节点创建订阅与路由表,不会在集群节点间广播全局路由,非常适合物联网数据采集应用. 使用方式: 订 ...