题目传送门

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

题解

貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树。

大概就是最终的答案很显然是随便选一个被标记的点作为根以后所有被标记的点之间的路径的并的长度的二倍。

可以发现这个东西就等于把所有的点按照 dfs 序排序以后的序列,相邻的点的距离和再加上最后一个点到第一个点的距离。

可以使用 std::set 维护。


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

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 1e5 + 7; int n, m, dfc;
ll ans;
int v[N];
ll dis[N];
int dep[N], f[N], siz[N], son[N], top[N], dfn[N], pre[N]; struct Edge { int to, ne, w; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].w = z, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, z); } inline void dfs1(int x, int fa = 0) {
f[x] = fa, dep[x] = dep[fa] + 1, siz[x] = 1;
for fec(i, x, y) if (y != fa) dis[y] = dis[x] + g[i].w, dfs1(y, x), siz[x] += siz[y], siz[y] > siz[son[x]] && (son[x] = y);
}
inline void dfs2(int x, int pa) {
top[x] = pa, dfn[x] = ++dfc, pre[dfc] = x;
if (!son[x]) return; dfs2(son[x], pa);
for fec(i, x, y) if (y != f[x] && y != son[x]) dfs2(y, y);
}
inline int lca(int x, int y) {
while (top[x] != top[y]) dep[top[x]] > dep[top[y]] ? x = f[top[x]] : y = f[top[y]];
return dep[x] < dep[y] ? x : y;
}
inline ll dist(int x, int y) { return dis[x] + dis[y] - (dis[lca(x, y)] << 1); } struct cmp {
inline bool operator () (const int &x, const int &y) { return dfn[x] < dfn[y]; }
};
std::set<int, cmp> s; inline void ins(int x) {
std::set<int, cmp>::iterator p = s.lower_bound(x);
int y = 0, z = 0;
if (p != s.end()) y = *p, ans += dist(x, y);
if (p != s.begin()) z = *--p, ans += dist(x, z);
if (y && z) ans -= dist(y, z);
s.insert(x);
}
inline void del(int x) {
s.erase(x);
std::set<int, cmp>::iterator p = s.lower_bound(x);
int y = 0, z = 0;
if (p != s.end()) y = *p, ans -= dist(x, y);
if (p != s.begin()) z = *--p, ans -= dist(x, z);
if (y && z) ans += dist(y, z);
} inline void work() {
dfs1(1), dfs2(1, 1);
while (m--) {
int x;
read(x);
if (!v[x]) v[x] = 1, ins(x);
else v[x] = 0, del(x);
if (s.empty()) puts("0");
else {
std::set<int, cmp>::iterator p = s.end();
--p;
// dbg("**** ans = %lld, *begin = %d, *end = %d, dist(4, 3) = %lld\n", ans, *s.begin(), *p, dist(4, 3));
printf("%lld\n", ans + dist(*s.begin(), *p));
}
}
} inline void init() {
read(n), read(m);
int x, y, z;
for (int i = 1; i < n; ++i) read(x), read(y), read(z), adde(x, y, z);
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj3991 [SDOI2015]寻宝游戏 树链的并的更多相关文章

  1. 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set

    [BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...

  2. 【bzoj3991】[SDOI2015]寻宝游戏 树链的并+STL-set

    题目描述 给出一棵树,初始每个点都是非必经的.多次改变某个点的必经状态,并询问从任意一个点出发,经过所有必经的点并回到该点的最小路程. 输入 第一行,两个整数N.M,其中M为宝物的变动次数. 接下来的 ...

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

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

  4. [BZOJ3991][SDOI2015]寻宝游戏

    [BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...

  5. CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏

    异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...

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

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

  7. bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并

    题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...

  8. BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】

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

  9. 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏

    在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...

随机推荐

  1. vue路由实例

    router.js: import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home ...

  2. selinux 关闭

    查看SELinux状态: 1./usr/sbin/sestatus -v      ##如果SELinux status参数为enabled即为开启状态 SELinux status:         ...

  3. redux源码浅入浅出

    运用redux有一段时间了,包括redux-thunk和redux-saga处理异步action都有一定的涉及,现在技术栈转向阿里的dva+antd,好用得不要不要的,但是需要知己知彼要对react家 ...

  4. Map 接口有哪些类

    Map接口 Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value:Map中的键值对以Entry类型的对象实例形式存在:建(key值)不 ...

  5. VMware 接入 Openstack — 使用 Openstack 创建 vCenter 虚拟机

    目录 目录 软件环境 前言 Openstack 接口驱动 使用 KVM 在 Compute Node 上创建虚拟机的流程 使用 VCDirver 在 vCenter 上创建虚拟机的流程 配置 vCen ...

  6. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_01 File类_6_File类判断功能的方法

    exists true表示路径是存在的 不存在的路径 不存在的路径返回false 相对路径的文件的判断 ‘ 不存在的相对路径 isDirectory和isFile 路径是不存在的 用这个方法之前最好先 ...

  7. 《计算机程式设计》Week3 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week3 Array 3-1 Array Usage 例子:使用数组一次申明10个整数变量 int a[10 ...

  8. 16/7/7_PHP-Static静态关键字

    Static静态关键字 静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用.静态属性不允许对象使用->操作符调用. class Car { private stat ...

  9. vue-methods方法与computed计算属性的差别

    好吧,我就是单纯的举个例子:实现显示变量 message 的翻转字符串 第一种:methods:我们可以通过在表达式中调用方法来达到同样的效果: 第二种:computed:计算属性 上面的2中方法都实 ...

  10. Java static关键字的重新思考

    上完Java课,虽然也写了不少的Java代码,但是一直有不少的疑惑,而static关键字一直困惑着我很久,今天无意探究竟,上知乎再仔细查了一下,发现了这个话题的优秀答案https://www.zhih ...