目录

题目链接

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. android camera(一):camera模组CMM介绍【转】

    转自:https://blog.csdn.net/kevinx_xu/article/details/8821818 androidcmm图像处理工作手机三星 关键词:android  camera ...

  2. WIN10 ISO 官方

    WIN10   ISO  官方: https://www.microsoft.com/zh-cn/software-download/windows10ISO/

  3. div里 datapicker显示异常的情况之一

    现象:datepicker控价显示一半 因为Div高度太小所以设置一个最小高度min-height这样就可以让时间控价显示完整了.

  4. win7安装Ubuntu变双系统以及删除Ubuntu分区操作

    Window7系统基础上安装Ubuntu使构成双系统,整个过程如下: 1. 一块空闲磁盘分区准备. “我的电脑”右键 > 管理 > 磁盘管理 > 压缩(从有空余分区压缩)/删除(删除 ...

  5. Redis消息通知(任务队列和发布订阅模式)

    Redis学习笔记(十)消息通知(任务队列和发布订阅模式) 1. 任务队列 1.1 任务队列的特点 任务队列:顾名思义,就是“传递消息的队列”.与任务队列进行交互的实体有两类,一类是生产者(produ ...

  6. Python3学习笔记15-迭代器与生成器

    生成器 如果创建一个有很多元素的列表,但是只需要访问前几个元素,后面的元素占着的空间就白白浪费了 在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间. 在Pytho ...

  7. C# 使用Win32 API将1个EXE程序嵌入另1个程序中

    已经干到天快亮了,就不废话直接贴点儿代码吧 ; ; /// <summary> /// 查找窗口 ///第一个参数是窗口的标题,第二个参数可直接用 null ///通过窗口的标题查找对应的 ...

  8. 【bzoj2653】【middle】【主席树+二分答案】

    Description 一个长度为 n 的序列 a ,设其排过序之后为 b ,其中位数定义为 b[n/2] ,其中 a,b 从 0 开始标号 , 除法取下整. 给你一个长度为 n 的序列 s .回答 ...

  9. Linux清除文件内容的几种方法

    # 清空或删除大文件内容的五种方法: # 法一:通过重定向到 Null 来清空文件内容 $ >test.sh # 法二:使用 ‘true' 命令重定向来清空文件 $ true > test ...

  10. 【转载】JavaScript中的属性:如何遍历属性

    转载自:http://www.cnblogs.com/ziyunfei/archive/2012/11/03/2752905.html 在JavaScript中,遍历一个对象的属性往往没有在其他语言中 ...