【LG3320】[SDOI2015]寻宝游戏

题面

洛谷

题解

不需要建虚树的虚树2333。。。

贪心地想一下,起始节点肯定是在关键点上,访问顺序就是\(dfs\)序。

那么对于每次询问,

\[Ans=dis(S_1,S_s)+\sum_{i=1}^{s-1}dis(S_i,S_{i+1})
\]

用\(set\)维护一下就好了

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
typedef long long ll;
const int MAX_N = 1e5 + 5;
struct Graph { int to, next, cost; } e[MAX_N << 1];
int fir[MAX_N], e_cnt;
void clearGraph() { memset(fir, -1, sizeof(fir)); }
void Add_Edge(int u, int v, int w) { e[e_cnt] = (Graph){v, fir[u], w}; fir[u] = e_cnt++; }
int N, M;
ll dis[MAX_N], ans;
int dep[MAX_N], size[MAX_N], top[MAX_N], son[MAX_N], fa[MAX_N], dfn[MAX_N], tim;
void dfs1(int x) {
size[x] = 1, dep[x] = dep[fa[x]] + 1;
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (v == fa[x]) continue;
dis[v] = dis[x] + e[i].cost;
fa[v] = x, dfs1(v), size[x] += size[v];
if (size[v] > size[son[x]]) son[x] = v;
}
}
void dfs2(int x, int tp) {
top[x] = tp, dfn[x] = ++tim;
if (son[x]) dfs2(son[x], tp);
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (v == fa[x] || v == son[x]) continue;
dfs2(v, v);
}
}
int LCA(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
ll DIS(int x, int y) { return dis[x] + dis[y] - 2ll * dis[LCA(x, y)]; }
struct cmp { bool operator () (int x, int y) const { return dfn[x] < dfn[y]; } } ;
set<int, cmp> s = set<int, cmp>(cmp());
set<int, cmp> :: iterator ite;
bool vis[MAX_N];
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
clearGraph();
N = gi(), M = gi();
for (int i = 1; i < N; i++) {
int u = gi(), v = gi(), w = gi();
Add_Edge(u, v, w), Add_Edge(v, u, w);
}
dfs1(1), dfs2(1, 1);
while (M--) {
int x = gi();
if (vis[x]) {
ite = s.find(x);
if (s.size() < 3) { ans = 0; goto P1; }
int pre, nxt;
if (ite == s.begin()) pre = *--s.end();
else pre = *(--ite), ++ite;
if (ite == --s.end()) nxt = *s.begin();
else nxt = *(++ite), --ite;
ans -= DIS(pre, x) + DIS(x, nxt) - DIS(pre, nxt);
P1 :
s.erase(ite);
} else {
ite = s.insert(x).first;
if (s.size() == 1) goto P2;
int pre, nxt;
if (ite == s.begin()) pre = *--s.end();
else pre = *(--ite), ++ite;
if (ite == --s.end()) nxt = *s.begin();
else nxt = *(++ite), --ite;
ans += DIS(pre, x) + DIS(x, nxt) - DIS(pre, nxt);
P2: ;
}
vis[x] ^= 1;
printf("%lld\n", ans);
}
return 0;
}

最新文章

  1. 分布式事务二阶提交DTS系统
  2. delphi dev 汉化
  3. Maven基础配置—上传jar包到私服
  4. zabbix监控模式、分布式、自动化
  5. haproxy log config
  6. How to manage the certificates in the PC
  7. directX学习系列8 颜色融合(转)
  8. Activity之间传递数据或数据包Bundle,传递对象,对象序列化,对象实现Parcelable接口
  9. Android 开源项目分类汇总
  10. bin文件格式分析
  11. NumPy基础练习(练一遍搞定NumPy)
  12. [Luogu 1395] 会议
  13. 搭建spring cloud config
  14. python调用数据返回字典dict数据的现象2
  15. 读C#开发实战1200例子记录-2017年8月14日10:03:55
  16. C#接口和泛型类
  17. 4、Flutter 采坑记录篇二_依赖库不兼容
  18. UVa - 10339
  19. 【转】Java设计模式之《享元模式》及应用场景
  20. amazon建立基于centos的ec2

热门文章

  1. 让IE6、7、8兼容@media属性
  2. SEO搜索引擎优化(转)
  3. BZOJ 1084 最大子矩阵 dp
  4. flume MemoryChannel 源代码解析
  5. [USACO08JAN]Telephone Lines
  6. 关于numpy mean函数的axis参数
  7. POJ 2299 Ultra-QuickSort 求逆序数 (归并或者数状数组)此题为树状数组入门题!!!
  8. activeMQ的spring、springboot的DEMO
  9. archLinux 学习笔记--mlocate的安装与使用
  10. Redis底层数据类型