3991: [SDOI2015]寻宝游戏

https://www.lydsy.com/JudgeOnline/problem.php?id=3991

分析:

  虚树+set。

  要求树上许多点之间的路径的总长的2倍。就是虚树。

  结论:如果将所有的点按dfs序拍好,答案就是相邻点之间的路径长度的和*2。所以这个可以按dfn维护一个set,每次操作查找前驱后继。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int INF = 1e9;
const int N = ; int head[N], nxt[N << ], to[N << ], len[N << ], En;
int deth[N], bel[N], siz[N], son[N], fa[N], id[N], dfn[N], TimeIndex;
LL dis[N];
bool vis[N];
LL tmp, Ans;
set<int> s;
set<int> :: iterator it; void add_edge(int u,int v,int w) {
++En; to[En] = v; len[En] = w; nxt[En] = head[u]; head[u] = En;
++En; to[En] = u; len[En] = w; nxt[En] = head[v]; head[v] = En;
} void dfs1(int u) {
deth[u] = deth[fa[u]] + ;
for (int i=head[u]; i; i=nxt[i]) {
int v = to[i];
if (v == fa[u]) continue;
dis[v] = dis[u] + len[i];
fa[v] = u;
dfs1(v);
siz[u] += siz[v];
if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;
}
} void dfs2(int u,int top) {
bel[u] = top;
dfn[u] = ++TimeIndex; id[TimeIndex] = u;
if (!son[u]) return ;
dfs2(son[u], top);
for (int i=head[u]; i; i=nxt[i]) {
int v = to[i];
if (v != fa[u] && v != son[u]) dfs2(v, v);
}
} int LCA(int u,int v) {
while (bel[u] != bel[v]) {
if (deth[bel[u]] < deth[bel[v]]) swap(u, v);
u = fa[bel[u]];
}
return deth[u] < deth[v] ? u : v;
} LL getdis(int x,int y) {
int lca = LCA(x, y);
return dis[x] + dis[y] - (dis[lca] * );
} void ins(int x) {
int L = *(--s.lower_bound(dfn[x]));
int R = *(s.upper_bound(dfn[x]));
if (L != -INF) Ans += getdis(id[L], x);
if (R != INF) Ans += getdis(id[R], x);
if (L != -INF && R != INF) Ans -= getdis(id[L], id[R]);
s.insert(dfn[x]); vis[x] = ;
} void del(int x) {
s.erase(dfn[x]); vis[x] = ;
int L = *(--s.lower_bound(dfn[x]));
int R = *(s.upper_bound(dfn[x]));
if (L != -INF) Ans -= getdis(id[L], x);
if (R != INF) Ans -= getdis(id[R], x);
if (L != -INF && R != INF) Ans += getdis(id[L], id[R]);
} int main() {
int n = read(), Q = read();
for (int i=; i<n; ++i) {
int u = read(), v = read(), w = read();
add_edge(u, v, w);
}
dfs1();
dfs2(, ); s.insert(-INF), s.insert(INF); while (Q--) {
tmp = ;
int x = read();
if (!vis[x]) ins(x);
else del(x);
if (s.size() > ) {
it = s.begin();
int L = *(++it);
it = s.end();
int R = *(--(--it));
tmp = getdis(id[L], id[R]);
}
printf("%lld\n",Ans + tmp);
}
return ;
}

3991: [SDOI2015]寻宝游戏的更多相关文章

  1. bzoj 3991: [SDOI2015]寻宝游戏 虚树 set

    目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...

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

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

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

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

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

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

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

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

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

    题意 给一个\(n\)个点带边权的树.有\(m\)次操作,每一次操作一个点\(x\),如果\(x\)已经出现,则\(x\)消失.否则\(x\)出现.每一操作后,询问从某个点开始走,直到经过所有出现的点 ...

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

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

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

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

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

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

随机推荐

  1. Task ‘run’ not found in root project

    问题现象: Task 'run' not found in root project 'springframework'. 问题原因: 没有在gradle.build文件中添加如下配置, mainCl ...

  2. 【Hankson 的趣味题】

    可能我只适合这道题的50分 但还是要争取一下的 我们知道对于\(gcd\)和\(lcm\)有这样的定义 \(a=\prod _{i=1}^{\pi(a)}p_i^{d_{i}}\) \(b=\prod ...

  3. redis安装和简介(2)

    承接上篇未完成的配置...此次使用的的 Redis-x64-3.2.100 版本 一.打开redis服务器 方式一:打开 redis-server.exe 显示如下图: 图中: 显示运行进程号.当前运 ...

  4. [转]C# 指针之美

     将C#图像库的基础部分开源了(https://github.com/xiaotie/GebImage).这个库比较简单,且离成熟还有一段距离,但它是一种新的开发模式的探索:以指针和非托管内存为主的C ...

  5. mime中间件

    mime中间件Demo,里面用到的有 1.path模块 //引入模块 var path=require('path'); 2.extname方法 //获取文件的扩展名 var extname=path ...

  6. android中OpenMax的实现【3】OMX中主要成员

    原文 http://blog.csdn.net/tx3344/article/details/8117908 通过上文知道了,每个AwesomePlayer 只有一个OMX服务的入口,但是Awesom ...

  7. NodeJs——入门

    关于NPM: npm 是 nodejs 的包管理和分发工具.它可以让 javascript 开发者能够更加轻松的共享代码和共用代码片段,并且通过 npm 管理你分享的代码也很方便快捷和简单. 一 No ...

  8. 执行SQL查询导致磁盘耗尽故障演示

            a fellow in IMG wechat group 2 met an error about running out of disk space when using MySQL ...

  9. ssh登录等待时间超时问题的解决

    最近使用ssh登录服务器时,发现许多服务器会报告等待时间超时的错误,通过网上查找发现是由于ssh中的配置中开启了DNS反查的功能,导致在反查过程中消耗了很长的时间,现将解决方法总结如下: 使用root ...

  10. 用VMWare搭建服务器集群不能上外网的三种模式下对应解决办法

    前言 决心要花费宝贵时间写下这篇心得,是因为从昨天晚上到今天上午被这个VMWare模拟搭建的服务器集群不能上外网的问题搞得很心烦,最后决定跟它杠上了!上午还通过远程连接得到了“空白”同学的帮助,在此表 ...