[BZOJ3991][SDOI2015]寻宝游戏
[BZOJ3991][SDOI2015]寻宝游戏
试题描述
输入
第一行,两个整数N、M,其中M为宝物的变动次数。
输出
M行,每行一个整数,其中第i行的整数表示第i次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出0。
输入示例
输出示例
数据规模及约定
1<=N<=100000
1<=M<=100000
对于全部的数据,1<=z<=10^9
题解
#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]寻宝游戏的更多相关文章
- CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏
异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...
- [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set
寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护
之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...
- bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并
题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...
- 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏
在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...
- bzoj3991 [SDOI2015]寻宝游戏 树链的并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...
- 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set
[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
随机推荐
- c# 正则表达式分组
internal class Program { private static void Main(string[] args) { var content = Read(@"E:\work ...
- 比较oracle数据的表结构
对比不同用户对象的异同,同时生成sql语句或直接提交到数据库,powerdesinger的比较实在是麻烦. pl/sql为我们提供了很好的工具 在pl/sql中的工具下“比较用户对象”,下即可实现:
- 自然语言19_Lemmatisation
QQ:231469242 欢迎喜欢nltk朋友交流 https://en.wikipedia.org/wiki/Lemmatisation Lemmatisation (or lemmatizatio ...
- 关于软件工程结对编程作业 PairProject : Elevator Scheduler(电梯调度算法的实现与测试)的总结
1)结对编程队友 1106xxxx 张扬 1106xxxx 杨军 其中,此项目的编程实现主要由前者完成. 2)关于结对编程 结对编程的优点: 最直接的一点:在结对编程中,由于有另一个人在你身边和你配合 ...
- C++中引用与指针的区别(详细介绍)
C++中引用与指针的区别(详细介绍) C++中的引用与指针的区别 指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一 ...
- My latest news (--2016.10)
2016.10.31 22:44 一个“程序”,打代码占40%.思考占60% 2016.10.30 20:53 周末,话说今天有晚上讲座,还点名,了,悲催.之前学习的Qt有点问题,悲催.推荐个博文:h ...
- 入门:HTML表单与Java 后台交互(复选框提交)
仅仅给出部分关键代码: HTML form code: <form action="JavaFormTest" method="post" name=&q ...
- python 多线程学习
多线程(multithreaded,MT),是指从软件或者硬件上实现多个线程并发执行的技术 什么是进程? 计算机程序只不过是磁盘中可执行的二进制(或其他类型)的数据.它们只有在被读取到内存中,被操作系 ...
- Linux--文件查找命令
一.简介查找文件的几个命令: 1.which :查找可执行文件的位置 2.whereis:查找文件的位置,可以找到可执行命令和man page 3.locate:配合数据库查看文件位置 4.find: ...
- win8.1企业版 IIS8.5 安装php5.5.18详细图文
最近为了做测试需要在电脑上安装php 环境如下 系统 win8.1 企业版 IIS 8.5 PHP:5.5.18 php-5.5.18-nts-Win32-VC11-x64 完整文件名 注意IIS 下 ...