目录

题目链接

bzoj 3991: [SDOI2015]寻宝游戏

题解

发现每次答案就是把虚树上的路径*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的更多相关文章

  1. BZOJ 3991: [SDOI2015]寻宝游戏 [虚树 树链的并 set]

    传送门 题意: $n$个点的树,$m$次变动使得某个点有宝物或没宝物,询问每次变动后集齐所有宝物并返回原点的最小距离 转化成有根树,求树链的并... 两两树链求并就可以,但我们按照$dfs$序来两两求 ...

  2. 【BZOJ】3991: [SDOI2015]寻宝游戏 虚树+DFS序+set

    [题意]给定n个点的带边权树,对于树上存在的若干特殊点,要求任选一个点开始将所有特殊点走遍后返回.现在初始没有特殊点,m次操作每次增加或减少一个特殊点,求每次操作后的总代价.n,m<=10^5. ...

  3. BZOJ 3991: [SDOI2015]寻宝游戏 树链的并+set

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

  4. bzoj 3991: [SDOI2015]寻宝游戏

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

  5. 树形结构的维护:BZOJ 3991: [SDOI2015]寻宝游戏

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

  6. BZOJ.3991.[SDOI2015]寻宝游戏(思路 set)

    题目链接 从哪个点出发最短路径都是一样的(最后都要回来). 脑补一下,最短路应该是按照DFS的顺序,依次访问.回溯遍历所有点,然后再回到起点. 即按DFS序排序后,Ans=dis(p1,p2)+dis ...

  7. [BZOJ 3991][SDOI2015]寻宝游戏(dfs序)

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

  8. 3991: [SDOI2015]寻宝游戏

    3991: [SDOI2015]寻宝游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=3991 分析: 虚树+set. 要求树上许多点之间的路径的 ...

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

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

随机推荐

  1. OpenCV:Debug和Release模式 && 静态和动态编译

    1.Release和Debug的区别 Release版称为发行版,Debug版称为调试版. Debug中可以单步执行.跟踪等功能,但生成的可执行文件比较大,代码运行速度较慢.Release版运行速度较 ...

  2. Linux内存管理--物理内存分配【转】

    转自:http://blog.csdn.net/myarrow/article/details/8682819 1. First Fit分配器 First Fit分配器是最基本的内存分配器,它使用bi ...

  3. 关于MySQL 8.0的几个重点【转】

    转自 关于MySQL .0的几个重点,都在这里 https://mp.weixin.qq.com/s/QUpk9uuS2JTli1GT6HuORA 一.关于MySQL Server的改进 1.1 re ...

  4. python的技巧和方法你了解多少?

    学了这些你的python代码将会改善与你的技巧将会提高. 1. 路径操作 比起os模块的path方法,python3标准库的pathlib模块的Path处理起路径更加的容易. 获取当前文件路径 前提导 ...

  5. Python3学习笔记20-获取对象信息

    当我们拿到一个对象的引用时,如何知道这个对象是什么类型.有哪些方法呢? 基本类型都可以用type()判断: print(type(123)) print(type('str')) print(type ...

  6. bat判断ini文件内容

    @echo off for /f "tokens=1" %%d in (config.ini) do ( if /I "%%d" equ "path= ...

  7. eclipse 反编译

    Eclipse Class Decompiler安装此插件,可以编译源代码且调试

  8. spring事物深入了解

    1.问题 1.以前对事物的了解只是停留在声明式事物,配置xml,或使用注解,事物的传播行为也只用过REQUIRED和SUPPORTS,可以说对事物的了解很模糊. 2.直到在开发中遇到问题.. 问题的描 ...

  9. Expm 7_1树中的最大独立集问题

    [问题描述] 给定一个无回路的无向图(即树),设计一个动态规划算法,求出该图的最大独立集,并输出该集合中的各个顶点值. package org.xiu68.exp.exp7; import java. ...

  10. 在Linux上安装go-gtk

    由于Linux的Gnome桌面就是用GTK编写的,所以,Linux本身就包含GTK工具库,安装GTK工具库在线安装即可. 第一步:在终端输入: sudo apt-get install libgtk3 ...