您的位置:首页 > 其它

BZOJ3991 [SDOI2015]寻宝游戏

2015-04-23 21:42 295 查看
易知,答案就是各个关键点之间形成的树的边权和的两倍,哦。。就是虚树

对于一颗虚树,答案就是各个的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: