BZOJ3991 [SDOI2015]寻宝游戏
2015-04-23 21:42
295 查看
易知,答案就是各个关键点之间形成的树的边权和的两倍,哦。。就是虚树
对于一颗虚树,答案就是各个的dfs序排序,相邻两点的距离和,再加上最后一个到第一个的距离
直接用set维护dfs序就好了
注意最后要剪掉所有关键点的LCA的深度
View Code
对于一颗虚树,答案就是各个的dfs序排序,相邻两点的距离和,再加上最后一个到第一个的距离
直接用set维护dfs序就好了
注意最后要剪掉所有关键点的LCA的深度
/************************************************************** Problem: 3991 User: rausen Language: C++ Result: Accepted Time:7304 ms Memory:42584 kb ****************************************************************/ #include <cstdio> #include <algorithm> #include <set> using namespace std; const int N = 1e5 + 5; typedef long long ll; typedef set<int> :: iterator iter; struct edge { int next, to, v; edge(int _n = 0, int _t = 0, int _v = 0) : next(_n), to(_t), v(_v) {} } e[N << 1]; struct tree_node { int fa, w, now; ll dis; } tr ; int n, m; int first , tot; int lg2[N << 1], cnt_seq; ll ans, st[N << 1][20]; set<int> seq; inline int read(); inline void Add_Edges(int x, int y, int z) { e[++tot] = edge(first[x], y, z), first[x] = tot; e[++tot] = edge(first[y], x, z), first[y] = tot; } #define y e[x].to void dfs(int p) { int x; st[tr[p].w = ++cnt_seq][0] = tr[p].dis; for (x = first[p]; x; x = e[x].next) if (y != tr[p].fa) { tr[y].fa = p, tr[y].dis = tr[p].dis + e[x].v; dfs(y); st[++cnt_seq][0] = tr[p].dis; } } #undef y ll query(int x, int y) { static int t; t = lg2[y - x + 1]; return min(st[x][t], st[y - (1 << t) + 1][t]); } template <class T> inline T nxt(const T &it) { static T tmp; tmp = it; return ++tmp; } template <class T> inline T pre(const T &it) { static T tmp; tmp = it; return --tmp; } inline void insert(int p) { static iter it; it = seq.insert(p).first; ans += st[p][0]; if (seq.size() == 1) return; if (it == seq.begin()) { ans -= query(*it, *nxt(it)); return; } if (nxt(it) == seq.end()) { ans -= query(*pre(it), *it); return; } ans += query(*pre(it), *nxt(it)) - query(*pre(it), *it) - query(*it, *nxt(it)); } inline void erase(int p) { static iter it; it = seq.find(p); ans -= st[p][0]; if (seq.size() == 1) { seq.erase(it); return; } if (it == seq.begin()) { ans += query(*it, *nxt(it)); seq.erase(it); return; } if (nxt(it) == seq.end()) { ans += query(*pre(it), *it); seq.erase(it); return; } ans -= query(*pre(it), *nxt(it)) - query(*pre(it), *it) - query(*it, *nxt(it)); seq.erase(it); } ll LCA() { if (seq.size() == 0) return 0ll; return query(*seq.begin(), *pre(seq.end())); } int main() { int i, j, x, y, z; n = read(), m = read(); for (i = 1; i < n; ++i) { x = read(), y = read(), z = read(); Add_Edges(x, y, z); } dfs(1); for (lg2[1] = 0, i = 2; i <= cnt_seq; ++i) lg2[i] = lg2[i >> 1] + 1; for (j = 1; j <= lg2[cnt_seq]; ++j) for (i = 1; i + (1 << j) - 1 <= cnt_seq; ++i) st[i][j] = min(st[i][j - 1], st[i + (1 << j - 1)][j - 1]); for (i = 1; i <= m; ++i) { x = read(); if (tr[x].now) tr[x].now = 0, erase(tr[x].w); else tr[x].now = 1, insert(tr[x].w); printf("%lld\n", ans - LCA() << 1); } return 0; } inline int read() { static int x, sgn; static char ch; x = 0, sgn = 1, ch = getchar(); while (ch < '0' || '9' < ch) { if (ch == '-') sgn = -1; ch = getchar(); } while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return sgn * x; }
View Code
相关文章推荐
- 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏
- BZOJ 3991: [SDOI2015]寻宝游戏
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
- BZOJ 3991 SDOI 2015 寻宝游戏(异象石) LCA + Set + DFS序
- BZOJ 3991: [SDOI2015]寻宝游戏
- [BZOJ3991]SDOI2015寻宝游戏|set|虚树
- bzoj 3991: [SDOI2015]寻宝游戏 (set+LCA+dfs序+虚树)
- 【BZOJ】【3991】【SDOI2015】寻宝游戏
- 树形结构的维护:BZOJ 3991: [SDOI2015]寻宝游戏
- 【BZOJ 3991】[SDOI2015]寻宝游戏 虚树
- 【bzoj3991】【SDOI2015】【寻宝游戏】【dfs序】
- bzoj 3991: [SDOI2015]寻宝游戏 dfs序+虚树+set
- BZOJ 3991 [SDOI2015]寻宝游戏
- bzoj3991 [SDOI2015]寻宝游戏
- 【BZOJ3991】【SDOI2015】寻宝游戏
- 【SDOI2015】bzoj3991 寻宝游戏
- BZOJ3991: [SDOI2015]寻宝游戏
- [BZOJ3991][SDOI2015]寻宝游戏(dfs序+set/平衡树)
- BZOJ 3991: [SDOI2015]寻宝游戏 [虚树 树链的并 set]
- bzoj3991 [SDOI2015]寻宝游戏