题目描述

给出一棵树,初始每个点都是非必经的。多次改变某个点的必经状态,并询问从任意一个点出发,经过所有必经的点并回到该点的最小路程。

输入

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

接下来的N-1行,每行三个整数x、y、z,表示村庄x、y之间有一条长度为z的道路。
接下来的M行,每行一个整数t,表示一个宝物变动的操作。若该操作前村庄t内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

输出

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

样例输入

4 5
1 2 30
2 3 50
2 4 60
2
3
4
2
1

样例输出

0
100
220
220
280


题解

树链的并+STL-set

考虑指定某个点为根,如果从根节点出发的话,答案显然是所有必经点到根节点的树链的并的长度*2。

我们维护这个树链的并:把所有点按照dfs序排序,每个点到根的距离减去排序后相邻两点LCA到根的距离就是树链的并的长度。本题由于需要支持插入和删除,因此可以使用STL-set。

但是这并不是最优解。考虑重复经过了哪一段:所有相邻两点LCA中深度最小的到根节点的距离。也即按dfs序排序后第一个点和最后一个点的LCA到根节点的距离。因此再使用set统计一下答案即可。

时间复杂度 $O(n\log n)$

#include <set>
#include <cstdio>
#define N 100010
using namespace std;
typedef long long ll;
set<int> s;
int head[N] , to[N << 1] , len[N << 1] , next[N << 1] , cnt , fa[N][20] , deep[N] , log[N] , pos[N] , ref[N] , tot , vis[N];
ll dis[N];
inline void add(int x , int y , int z)
{to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{int i;pos[x] = ++tot , ref[tot] = x;for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];for(i = head[x] ; i ; i = next[i])if(to[i] != fa[x][0])fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , dis[to[i]] = dis[x] + len[i] , dfs(to[i]);
}
inline int lca(int x , int y)
{int i;if(deep[x] < deep[y]) swap(x , y);for(i = log[deep[x] - deep[y]] ; ~i ; i -- )if((1 << i) <= deep[x] - deep[y])x = fa[x][i];if(x == y) return x;for(i = log[deep[x]] ; ~i ; i -- )if((1 << i) <= deep[x] && fa[x][i] != fa[y][i])x = fa[x][i] , y = fa[y][i];return fa[x][0];
}
int main()
{int n , m , i , x , y , z;set<int>::iterator it;ll now = 0;scanf("%d%d" , &n , &m);for(i = 2 ; i <= n ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z) , log[i] = log[i >> 1] + 1;dfs(1);while(m -- ){scanf("%d" , &x) , y = z = 0;if(!vis[x]){it = s.upper_bound(pos[x]);if(it != s.end()) y = ref[*it];if(it != s.begin()) z = ref[*--it];if(y) now -= dis[lca(x , y)];if(z) now -= dis[lca(x , z)];if(y && z) now += dis[lca(y , z)];now += dis[x] , vis[x] = 1 , s.insert(pos[x]);}else{now -= dis[x] , vis[x] = 0 , s.erase(pos[x]);it = s.upper_bound(pos[x]);if(it != s.end()) y = ref[*it];if(it != s.begin()) z = ref[*--it];if(y) now += dis[lca(x , y)];if(z) now += dis[lca(x , z)];if(y && z) now -= dis[lca(y , z)];}if(s.size() < 2) puts("0");else printf("%lld\n" , (now - dis[lca(ref[*s.begin()] , ref[*--s.end()])]) << 1);}return 0;
}

转载于:https://www.cnblogs.com/GXZlegend/p/8059408.html

【bzoj3991】[SDOI2015]寻宝游戏 树链的并+STL-set相关推荐

  1. 【BZOJ 3991】 [SDOI2015]寻宝游戏

    3991: [SDOI2015]寻宝游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 251 Solved: 137 [Submit][Status ...

  2. SDOI2015寻宝游戏 dfs序+set

    SDOI2015寻宝游戏 好像是一道虚树入门题? 虚树???不会不会我弱死了.. Solution: 关键点间的最小路径,就是在保证尽量少走重复路的前提下走出来的一条经过所有关键点的路径. 基于这个思 ...

  3. 【SDOI2015】【BZOJ3991】寻宝游戏

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

  4. [ZJOI2015] 幻想乡战略游戏——树链剖分

    [ZJOI2015]幻想乡战略游戏 题解 由于所有边的边权是正整数,所以可以发现任何时刻每个点的答案是从最优的点往周围递增的.如果有平台,那么一定是在最优点的连通块那儿. 我们先考虑如何快速求每个点的 ...

  5. 【bzoj3991】 寻宝游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=3991 (题目链接) 题意:给出一个n个节点的带权树,m次操作每次修改一个关键点,求每次操作后,从其中 ...

  6. BZOJ 3991: [SDOI2015]寻宝游戏

    随便选一个点当做根,跑每个点的深度(为了求LCA)d [ u ] ,和到根节点的距离(为了更新答案) l [ u ] 我们发现,由关键点和他们的LCA构成的虚树(其实就是忽略其他节点),由于还要回到原 ...

  7. 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)

    被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...

  8. 洛谷 P3320: bzoj 3991: LOJ 2182: [SDOI2015]寻宝游戏

    题目传送门:LOJ #2182. 题意简述: 一棵 \(n\) 个节点的树,边有边权. 每个点可能是关键点,每次操作改变一个点是否是关键点. 求所有关键点形成的极小联通子树的边权和的两倍. 题解: 有 ...

  9. [ZJOI2015] 幻想乡战略游戏(树链剖分 + 线段树二分 + 带权重心)

    problem luogu-P3345 solution 这是一个带权重心的题,考察动态点分治.点分治?呵,不可能的,这辈子都不可能写点分治 我们重新考虑重心的性质:以这个点为根时,所有子树的大小不会 ...

最新文章

  1. dataTables-使用详细说明整理
  2. Git回滚代码到某个commit
  3. 成功解决AttributeError: module 'cv2.cv2' has no attribute 'CV_CAP_PROP_FPS'和 'CV_CAP_PROP_FRAME_WIDTH'
  4. 行情分发速度为王,谁是证券公司的生命线?
  5. mysql在cmd命令行下的相关操作
  6. 图注意力网络_EMNLP 2019开源论文:针对短文本分类的异质图注意力网络
  7. 计算机视觉论文-2021-06-21
  8. 禅道设置bug模板_禅道的自定义功能:表格切换和创建页面的自定义
  9. AI队列长度检测:使用YOLO进行图像中的对象检测
  10. HenCoder Android 自定义 View 1-6:属性动画(上手篇)
  11. 基于Java毕业设计银行贷款管理系统源码+系统+mysql+lw文档+部署软件
  12. php trim /r/n,「php中trim函数使用」- 海风纷飞Blog
  13. C# 操作Word页眉页脚——奇偶页/首页不同、不连续设置页码、复制页眉页脚、锁定页眉页脚、删除页眉页脚...
  14. 怎么计算中国股市分红最高的股票?什么是股息率?--使用python和tushare获取分红最高的股票
  15. Excel报表的导出
  16. 各种风格404错误页面html模板源码30多套高大尚响应式网站模板html5网页静态模板Bootstrap扁平化网站源码css3手机seo自适响应。
  17. 计算机电池维修心得,CMOS电池引起计算机无法启动的检修详解
  18. 操盘手的灵魂 - 交易纪律
  19. 云计算专业防火墙混合模式应用实验
  20. LUNA16结节可视化及世界(CT)坐标与体素(图像)坐标的转换

热门文章

  1. 中海达数据怎么转rinex_hds2003下载-中海达HDS2003数据处理软件下载20120530 官方版-中海达GPS数据转RINEX格式西西软件下载...
  2. java获取子路径_Java中路径的获取
  3. php callable 参数,php 利用反射执行callable
  4. 日期格式化为yyyymmdd_你还在用SimpleDateFormat格式化时间嘛
  5. 辽源天气预报软件测试,辽源天气预报15天
  6. oracle判断数据出现交叉,Oracle move table分析
  7. gdb tui 安装_GDB 单步调试汇编
  8. Spring AOP是什么?
  9. 华为仿苹果字体_华为mate40系列再次霸榜DXO,网友:无敌是多么寂寞
  10. python基础入门(6)之列表