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. commons dbcp.jar有什么用

    主流数据库连接池之一(DBCP.c3p0.proxool),单独使用DBCP需要使用commons-dbpc.jar.commons-collections.jar.commons-pool.jar三 ...

  2. 勒让德定理---阶乘中素因子p的指数

  3. Java 中 Vector 和 ArrayList 的区别

    首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList.Vector和LinkedList.List用于存放多个元素,能够维护元素的次序,并且允许元素的重复.3个具体 ...

  4. [objc explain]: Non-fragile ivars

    [objc explain]: Non-fragile ivars   (2009-01-27 09:30 PM)   Non-fragile instance variables are a hea ...

  5. 如何理解“Unix 里一切都是文件”这句话-在 UNIX 中,一切都是字节流

    UNIX 操作系统的设计.用户界面.文化和演变都是建立在它的一套统一的想法和概念上.其中最重要的一点可能是“一切皆文件”,而这个概念被认为是 UNIX 的灵魂之一. 这一关键设计原则提供了一个统一的范 ...

  6. thinkphp5.0调用ajax无刷新加载数据

    控制器层那边就是调数据返回,这里不再赘述,视图层页面ajax部分写法如下 function shanchu(obj) { var code = $(obj).attr("code" ...

  7. 9.spring:事务管理(下):声明式事务管理

    声明式事务管理 sprin的声明式事务是管理AOP技术实现的事务管理,其本质是是对方法前后进行拦截,然后 在目标方法开始之前创建或者加入一个事务,在执行完成目标方法之后根据执行情况提交或者回滚事务. ...

  8. javascript中的回调函数(callback) (转载)

    代码如下: app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(er ...

  9. MySQL性能优化总结(转)

    MySQL性能优化总结   一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存 ...

  10. Lambda使用

    说明 本文内容来自 [Java8 In Action] 一书 四种方法引用类型 类型 示例 引用静态方法 ContainingClass::staticMethodName 引用某个对象的实例方法 c ...