Luogu 3320 [SDOI2015]寻宝游戏
一开始还真没想到。
发现从所有有宝藏的点出发绕一圈只要不刻意绕路答案都是一样的,即我们呢要求的最后答案$ans = dis(x_1, x_2) + dis(x_2, x_3) +... + dis(x_{k - 1}, x_k) + dis(x_k, x_1)$。
不刻意绕远路怎么办呢,我们把有宝藏的点按照$dfs$序,维护一个有序的$set$就可以了。
每次插入就相当于找到一个点$x$在$dfs$序中的前一个点$lst$和后一个点$nxt$,使最后的答案减去$dis(nxt, lst)$并加上$dis(x, nxt) + dis(lst, x)$,删除同理。
我选择用倍增来求$dis(x, y)$。
$set$的细节一开始没想清楚,写了一会儿。
时间复杂度$O(nlogn)$。
Code:
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
typedef long long ll; const int N = 1e5 + ;
const int Lg = ; int n, qn, tot = , head[N];
int dep[N], fa[N][Lg], dfsc = , id[N], mp[N];
ll ans = 0LL, dis[N];
bool ex[N];
set <int> s; struct Edge {
int to, nxt;
ll val;
} e[N << ]; inline void add(int from, int to, ll val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} void dfs(int x, int fat, int depth, ll nowDis) {
fa[x][] = fat, dep[x] = depth, dis[x] = nowDis;
id[x] = ++dfsc, mp[id[x]] = x;
for(int i = ; i <= ; i++)
fa[x][i] = fa[fa[x][i - ]][i - ];
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs(y, x, depth + , nowDis + e[i].val);
}
} inline void swap(int &x, int &y) {
int t = x; x = y; y = t;
} inline int getLca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y])
x = fa[x][i];
if(x == y) return x;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][];
} inline ll getDis(int x, int y) {
int z = getLca(x, y);
return dis[x] + dis[y] - * dis[z];
} int main() {
read(n), read(qn);
for(int x, y, i = ; i < n; i++) {
read(x), read(y);
ll v; read(v);
add(x, y, v), add(y, x, v);
}
dfs(, , , 0LL); /* for(int i = 1; i <= n; i++)
printf("%d ", id[i]);
printf("\n"); */ for(int x, cnt = ; qn--; ) {
read(x);
if(!ex[x]) {
ex[x] = ;
s.insert(id[x]);
++cnt;
if(cnt == ) {
puts("");
continue;
}
set <int> :: iterator it = s.find(id[x]), it2 = it;
if(it == s.begin()) it = s.end();
int lst = *(--it);
it = s.find(id[x]);
int nxt = ;
if((++it2) == s.end()) nxt = *(s.begin());
else nxt = *(++it);
ans += getDis(mp[lst], x) + getDis(mp[nxt], x) - getDis(mp[lst], mp[nxt]);
} else {
ex[x] = ;
--cnt;
if(cnt == ) {
puts("");
s.erase(id[x]);
continue;
}
set <int> :: iterator it = s.find(id[x]), it2 = it;
if(it == s.begin()) it = s.end();
int lst = *(--it);
it = s.find(id[x]);
int nxt = ;
if((++it2) == s.end()) nxt = *(s.begin());
else nxt = *(++it);
ans -= getDis(mp[lst], x) + getDis(mp[nxt], x) - getDis(mp[lst], mp[nxt]);
s.erase(id[x]);
}
printf("%lld\n", ans);
} return ;
}
Luogu 3320 [SDOI2015]寻宝游戏的更多相关文章
- Luogu P3320 [SDOI2015]寻宝游戏 / 异象石 【LCA/set】
期末考试结束祭! 在期末考试前最后一发的测试中,异象石作为第二道题目出现QAQ.虽然知道是LCA图论,但还是敲不出来QAQ. 花了两天竞赛课的时间搞懂(逃 异象石(stone.pas/c/cpp)题目 ...
- luogu P3320 [SDOI2015]寻宝游戏
大意:给定树, 要求维护一个集合, 支持增删点, 询问从集合中任取一点作为起点, 遍历完其他点后原路返回的最短长度. 集合中的点按$dfs$序排列后, 最短距离就为$dis(s_1,s_2)+...+ ...
- 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)
被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...
- [BZOJ3991][SDOI2015]寻宝游戏
[BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
- P3320 [SDOI2015]寻宝游戏 解题报告
P3320 [SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有\(N\)个村庄和\(N-1\)条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以 ...
- 【LG3320】[SDOI2015]寻宝游戏
[LG3320][SDOI2015]寻宝游戏 题面 洛谷 题解 不需要建虚树的虚树2333... 贪心地想一下,起始节点肯定是在关键点上,访问顺序就是\(dfs\)序. 那么对于每次询问, \[ An ...
- 3991: [SDOI2015]寻宝游戏
3991: [SDOI2015]寻宝游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=3991 分析: 虚树+set. 要求树上许多点之间的路径的 ...
- 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set
[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...
随机推荐
- Flask框架的学习与实战(二):实战小项目
昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统. blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全.这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达 ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(三)【转】
本文转载自:http://blog.csdn.net/mu0206mu/article/details/7464699 以下的篇幅开始分析我们在上两个篇幅中生成的update.zip包在具体更新中所经 ...
- Havel-Hakimi定理 POJ1659
对于图的所有顶点,计算出每个顶点的度,度序列.给定一个序列判断序列是否可图. #include<cstdio> #include<algorithm> #include< ...
- Linux初识(命令, 文件, 系统管理)
Linux初识(命令, 文件) 文件系统 在Linux系统下,没有驱动器磁盘,只有一个根目录 / ,所有的文件都在根目录下面. 相关文件夹介绍 bin : 程序相关 boot : 开机启动相关 cdr ...
- 大话设计模式--策略模式 strategy -- C++实现实例
1. 策略模式: 它定义了算法家族, 分别封装起来,使他们之间可以相互替换,此模式让算法变化, 不会影响到使用算法的客户. 用相同的方法调用不同的算法,减少各种算法类与使用算法类之间的耦合. 实例中策 ...
- Subnet Pools and Address Scopes
Why is IPAM important for Neutron? •No VM connectivity without a valid IP assigned •Duplicate subne ...
- Mysql远程链接访问权限设置
Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQL的远程帐号 如何开启MySQL的远程帐号-1)首先以 r ...
- java:类集操作总结
java:类集操作总结 1.List接口允许有重复的元素,Set接口中不允许有重复的元素 2.ArrayList,和Vector的区别 3.set依靠equals和hashCode区分 4.TreeS ...
- codeforces 710B B. Optimal Point on a Line(数学)
题目链接: B. Optimal Point on a Line 题意: 给出n个点,问找出一个点使得这个点到所有的点的距离和最小; 思路: 所有点排序后的中位数;这是一个结论; AC代码: #inc ...
- STL memory.cpp
memory.cpp # // Filename: memory # # // Comment By: 凝霜 # // E-mail: mdl2009@vip.qq.com # // Blog: ht ...