bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录
题目链接
题解
发现每次答案就是把虚树上的路径*2
接在同一关键点上的点的dfs序是相邻的
那么用set动态维护dfs序列
每次删点加点就好了
代码
#include<set>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define pc putchar
#define LL long long
inline int read() {
int x = 0,f = 1;
char c = gc;
while(c < '0' || c > '9') c = gc;
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc;
return x * f;
}
void print(LL x) {
if(x < 0) {
pc('-');
x = -x;
}
if(x >= 10) print(x / 10);
pc(x % 10 + '0');
}
const int maxn = 100007;
int n,m;
struct node {
int v,next,w;
} edge[maxn << 1];
int head[maxn],num = 0;
inline void add_edge(int u,int v,int w) {
edge[++ num].v = v; edge[num].w = w; edge[num].next = head[u];head[u] = num;
}
std::set<int>s;
std::set<int> :: iterator it,qi,ho;
int deep[maxn],top[maxn],fa[maxn],son[maxn],siz[maxn];
LL dis[maxn];
void dfs1(int x,int f) {
deep[x] = deep[f] + 1,fa[x] = f;
siz[x] = 1;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v != f) {
dis[v] = dis[x] + edge[i].w;
dfs1(v,x);
if(siz[v] > siz[son[x]]) son[x] = v;
siz[x] += siz[v];
}
}
}
int cnt = 0,dfn[maxn],ra[maxn];
void dfs2(int x,int tp) {
top[x] = tp; dfn[x] = ++ cnt;ra[cnt] = x;
if(son[x]) dfs2(son[x],tp);
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == fa[x] || v == son[x]) continue;
dfs2(v,v);
}
}
int lca(int x,int y) {
while(top[x] != top[y]) {
if(deep[top[x]] > deep[top[y]]) x = fa[top[x]];
else y = fa[top[y]];
}
return deep[x] > deep[y] ? y : x;
}
LL query(int x) {
it = s.find(dfn[x]);
if(it == s.begin()) {qi = s.end();qi --; }
else {qi = it ;qi --; }
ho = it;ho ++;
if(ho == s.end()) ho = s.begin();
return dis[ra[* ho]] + dis[ra[* it]] * 2 + dis[ra[* qi]] - dis[lca(ra[* ho],ra[* it])] * 2 - dis[lca(ra[* it],ra[* qi])] * 2;
}
bool vis[maxn];
LL work(int x) {
it = s.find(dfn[x]);
if(it == s.begin()) {qi = s.end();qi --; }
else {qi = it; qi --;}
ho = it;ho ++;
if(ho == s.end()) ho = s.begin();
return dis[ra[*ho]] + dis[ra[*qi]] - 2 * dis[lca(ra[*qi],ra[*ho])];
}
int main() {
n = read(),m = read();
for(int u,v,w,i = 1;i < n;++ i) {
u = read(),v = read(),w = read();
add_edge(u,v,w); add_edge(v,u,w);
}
LL ans = 0;
dfs1(1,0);
dfs2(1,1);
for(int i = 1;i <= m;++ i) {
int x = read();
if(vis[x]) {
ans -= query(x);
ans += work(x);
s.erase(dfn[x]),vis[x] = 0;
} else {
vis[x] = 1;
s.insert(dfn[x]);
ans -= work(x);
ans += query(x);
}
printf("%lld\n",ans);
}
return 0;
}
bzoj 3991: [SDOI2015]寻宝游戏 虚树 set的更多相关文章
- BZOJ 3991: [SDOI2015]寻宝游戏 [虚树 树链的并 set]
传送门 题意: $n$个点的树,$m$次变动使得某个点有宝物或没宝物,询问每次变动后集齐所有宝物并返回原点的最小距离 转化成有根树,求树链的并... 两两树链求并就可以,但我们按照$dfs$序来两两求 ...
- 【BZOJ】3991: [SDOI2015]寻宝游戏 虚树+DFS序+set
[题意]给定n个点的带边权树,对于树上存在的若干特殊点,要求任选一个点开始将所有特殊点走遍后返回.现在初始没有特殊点,m次操作每次增加或减少一个特殊点,求每次操作后的总代价.n,m<=10^5. ...
- BZOJ 3991: [SDOI2015]寻宝游戏 树链的并+set
Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可 ...
- bzoj 3991: [SDOI2015]寻宝游戏
Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可 ...
- 树形结构的维护:BZOJ 3991: [SDOI2015]寻宝游戏
Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可 ...
- BZOJ.3991.[SDOI2015]寻宝游戏(思路 set)
题目链接 从哪个点出发最短路径都是一样的(最后都要回来). 脑补一下,最短路应该是按照DFS的顺序,依次访问.回溯遍历所有点,然后再回到起点. 即按DFS序排序后,Ans=dis(p1,p2)+dis ...
- [BZOJ 3991][SDOI2015]寻宝游戏(dfs序)
题面 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- 3991: [SDOI2015]寻宝游戏
3991: [SDOI2015]寻宝游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=3991 分析: 虚树+set. 要求树上许多点之间的路径的 ...
- [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set
寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...
随机推荐
- move_base
1>准备导航所需要的包. a.ros-indigo-gampping :我们不需要修改包内的东西,所以直接安装可执行文件就好了. sudo apt-get install ros-indigo- ...
- 搭建Modelsim SE仿真环境-使用do文件仿真
本章我们介绍仿真环境搭建是基于Modelsim SE的.Modelsim有很多版本,比如说Modelsim-Altera,但是笔者还是建议大家使用Modelsim-SE,Modelsim-Altera ...
- 【转】Python之日期与时间处理模块(date和datetime)
[转]Python之日期与时间处理模块(date和datetime) 本节内容 前言 相关术语的解释 时间的表现形式 time模块 datetime模块 时间格式码 总结 前言 在开发工作中,我们经常 ...
- word文档里打不开公式 打开后都是方框
因为系统缺少一种字体,只要到网络上下载或到其他计算机中复制一种文件名为“symbol.ttf”的字体文件来安装上,就可以了.参考资料:Office之家 http://www.officejia.com ...
- xargs -i和-I的区别【转】
xargs与find经常结合来进行文件操作,平时删日志的时候只是习惯的去删除,比如 # find . -type f -name "*.log" | xargs rm -rf * ...
- llinux除了软连接本地文件夹同步:mount
mount --bind /srv/dir1 /srv/dir2dir1:被共享的文件夹dir2:需要同步的文件夹
- java中printf()方法简单用法
%n 换行 相当于 \n %c 单个字符 %d 十进制整数 %u 无符号十进制数 %f 十进制浮点数 %o 八进制数 %x 十六进制数 %s 字符串 %% 输出百分号 > 在printf()方法 ...
- 支付宝&微信统一支付
1.实体对应关系: Application — 支付记录实体 -- 支付记录详情 2.流程 1.生成订单选择支付类型 2.支付宝:PC端.手机端.扫码:微信:微信公众号支付.扫码支付.H5支付. ...
- App调试的几个命令实践【转】
在Android的应用开发中,我们会用到各种代码调试:其实在Android的开发之后,我们可能会碰到一些随机的问题,如cpu过高,内存泄露等,我们无法简单的进行代码调试,我们需要一个系统日志等等,下面 ...
- 【转载】如何让图片按比例响应式缩放、并自动裁剪的css技巧
原文: http://blog.csdn.net/oulihong123/article/details/54601030 响应式网站.移动端页面在DIV CSS布局中对于图片列表或图片排版时, 如果 ...