【BZOJ3991】【SDOI2015】寻宝游戏
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】寻宝游戏的更多相关文章
- [BZOJ3991][SDOI2015]寻宝游戏
[BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...
- CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏
异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...
- [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set
寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护
之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...
- bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并
题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...
- 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏
在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...
- bzoj3991 [SDOI2015]寻宝游戏 树链的并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...
- 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set
[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
随机推荐
- 团队作业7——第二次项目冲刺(Beta版本)
Deadline: 2017-12-10 23:00PM,以博客发表日期为准. 评分基准: 按时交 - 有分,检查的项目包括后文的三个方面 冲刺计划安排(单独1篇博客) 七天的敏捷冲刺(每两天发布 ...
- 201621123040《Java程序设计》第2周学习总结
1.本周学习总结 关键词:Java中的字符串与数组 c语言基本语法的迁移 相关总结:在一周的学习过程中,我自主学习Java的基本语法,前期的相关语法与c语言的基本语法相近,也算是做到了很好的回顾:在郑 ...
- 开启Linux的share
1.挂载Install Vmare Tool 2.解压VMwareTools.tar.gz 3.安装share目录 4.shared Folders Enabled 添加共享的目录. 在自己的Unb ...
- NetFPGA-1G-CML Demo --- openflow_switch
环境 ubuntu 14.04 vivado 15.2 ise 14.6 更多基础配置:http://www.cnblogs.com/wpqwpq/p/6771568.html 运行步骤 step1: ...
- memmove 和 memcpy的区别以及处理内存重叠问题
区别: memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, const v ...
- 详解k8s一个完整的监控方案(Heapster+Grafana+InfluxDB) - kubernetes
1.浅析整个监控流程 heapster以k8s内置的cAdvisor作为数据源收集集群信息,并汇总出有价值的性能数据(Metrics):cpu.内存.网络流量等,然后将这些数据输出到外部存储,如Inf ...
- java 零基础搭建dubbo运行环境
一:简介 以前做项目时,分布式环境都是其它同事在搭建,自己也没参与分布式环境搭建,只负责开发,由于近段时间工作重心转到android,java后台有一段时间没有接触了,刚好这几天有空,决定自己动 ...
- GZip 压缩及解压缩
/// <summary> /// GZipHelper /// </summary> public class GZipHelper { /// <summary> ...
- GIT入门笔记(19)GIT 小结
1.add和commit为什么Git添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:$ git add file1.txt$ g ...
- html的语法注意事项
html的语法 1.html不区分大小写,但是编写网页的时候尽量使用小写 2.文档注释:<!-- 注释部分的内容 --> 3.空格键和回车键在网页中不会起到任何作用 4.注意缩进时保持严格 ...