[BZOJ3991][SDOI2015]寻宝游戏

试题描述

小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达。游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小B需要不断地更新数据,但是小B太懒了,不愿意自己计算,因此他向你求助。为了简化问题,我们认为最开始时所有村庄内均没有宝物

输入

第一行,两个整数N、M,其中M为宝物的变动次数。

接下来的N-1行,每行三个整数x、y、z,表示村庄x、y之间有一条长度为z的道路。
接下来的M行,每行一个整数t,表示一个宝物变动的操作。若该操作前村庄t内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

输出

M行,每行一个整数,其中第i行的整数表示第i次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出0。

输入示例


输出示例


数据规模及约定

1<=N<=100000

1<=M<=100000

对于全部的数据,1<=z<=10^9

题解

见“[OpenJudge0054]特务会议召开”。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <set>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
#define maxm 200010
#define maxlog 20
#define LL long long
int n, m, head[maxn], next[maxm], to[maxm], dist[maxm]; void AddEdge(int a, int b, int c) {
to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
return ;
} int ord[maxn], Id[maxn], clo, dep[maxn], fa[maxlog][maxn];
LL Dep[maxn];
void build(int u) {
ord[u] = ++clo; Id[clo] = u;
for(int i = 1; i < maxlog; i++) fa[i][u] = fa[i-1][fa[i-1][u]];
for(int e = head[u]; e; e = next[e]) if(to[e] != fa[0][u]) {
fa[0][to[e]] = u;
dep[to[e]] = dep[u] + 1;
Dep[to[e]] = Dep[u] + dist[e];
build(to[e]);
}
return ;
}
int lca(int a, int b) {
if(dep[a] < dep[b]) swap(a, b);
for(int i = maxlog - 1; i >= 0; i--) if(dep[a] - (1 << i) >= dep[b]) a = fa[i][a];
for(int i = maxlog - 1; i >= 0; i--) if(fa[i][a] != fa[i][b]) a = fa[i][a], b = fa[i][b];
return a == b ? a : fa[0][b];
} bool sta[maxn];
set <int> S;
std :: set <int> :: iterator l, r; int main() {
n = read(); int q = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read(), c = read();
AddEdge(a, b, c);
}
build(1);
LL ans = 0;
while(q--) {
int x = read();
if(!sta[x]) {
sta[x] = 1;
if(S.size()) {
l = S.lower_bound(ord[x]);
if(l == S.begin()) l = S.end();
l--;
r = S.upper_bound(ord[x]);
if(r == S.end()) r = S.begin();
int c = lca(Id[*l], Id[*r]);
LL d = Dep[Id[*l]] + Dep[Id[*r]] - (Dep[c] << 1);
ans -= d;
c = lca(Id[*l], x);
d = Dep[Id[*l]] + Dep[x] - (Dep[c] << 1);
ans += d;
c = lca(x, Id[*r]);
d = Dep[x] + Dep[Id[*r]] - (Dep[c] << 1);
ans += d;
}
S.insert(ord[x]);
}
else {
sta[x] = 0;
S.erase(ord[x]);
if(S.size()) {
l = S.lower_bound(ord[x]);
if(l == S.begin()) l = S.end();
l--;
r = S.upper_bound(ord[x]);
if(r == S.end()) r = S.begin();
int c = lca(Id[*l], Id[*r]);
// printf("points: %d %d %d\n", Id[*r], Id[*r], c);
LL d = Dep[Id[*l]] + Dep[Id[*r]] - (Dep[c] << 1);
ans += d;
// printf("+ %lld\n", d);
c = lca(Id[*l], x);
d = Dep[Id[*l]] + Dep[x] - (Dep[c] << 1);
ans -= d;
// printf("- %lld\n", d);
c = lca(x, Id[*r]);
d = Dep[x] + Dep[Id[*r]] - (Dep[c] << 1);
ans -= d;
// printf("- %lld\n", d);
}
}
printf("%lld\n", ans);
} return 0;
}

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

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

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

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

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

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

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

  4. bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护

    之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...

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

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

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

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

  7. bzoj3991 [SDOI2015]寻宝游戏 树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...

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

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

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

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

随机推荐

  1. Python字典和集合

    Python字典操作与遍历: 1.http://www.cnblogs.com/rubylouvre/archive/2011/06/19/2084739.html 2.http://5iqiong. ...

  2. WinForm------GridControl显示每行的Indicator中的行号

    1.修改Indicator的行宽 2.添加CustomDrawRowIndicator事件 private void AdminCardView_CustomDrawRowIndicator(obje ...

  3. PHPCMSv9首页显示分页点击下一页跳转链接出现错误,跳转到后台的解决方案

    1 引用页写为 {pc:content action="lists" catid="10" order="updatetime DESC" ...

  4. 利用百度开发者中心的api实现地图及周边的搜索

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  5. Latent Semantic Analysis (LSA) Tutorial 潜语义分析LSA介绍 一

    Latent Semantic Analysis (LSA) Tutorial 译:http://www.puffinwarellc.com/index.php/news-and-articles/a ...

  6. IDEA 搭建的SpringMVC Maven项目出现的问题

    1.添加jar包时,报添加某个jar包有问题,在pom.xml文件的project节点上有红波浪线 jar引用的maven地址没有问题,就是报错 解决办法:到本地仓库把相关jar包删掉重新下载 2.各 ...

  7. Android学习笔记——Button

    该工程的功能是实现在activity中显示一个TextView和一个Button 以下代码是MainActivity中的代码 package com.example.button; import an ...

  8. JSP 原理

    参考文献:http://www.cnblogs.com/xdp-gacl/p/3764991.html 一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都 ...

  9. C# C++联调

    http://jingyan.baidu.com/article/fcb5aff7926344edab4a714d.html

  10. 找到一款不错的网站压力测试工具webbench

    webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 引用 wget htt ...