Problem’s Website
- 异象石
Solution
- 首先我们可以得出这是一颗树,我们可以用一些关于树的基本操作,比如我们可以求出节点的dfs序,根据dfs序升序排序,把异象石的节点首尾相连,累加相邻节点的路径长度,得到的结果正好是答案的两倍,可以画图观察一下。
- 那么我们可以用set来维护dfs序,用LCA来计算路径长度,就可以把这道题A掉。
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using namespace std;
int sc() {
int xx = 0, ff = 1; char cch = gc;
while (cch < '0' || cch > '9') {
if (cch == '-') ff = -1; cch = gc;
}
while (cch >= '0' && cch <= '9') {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
struct TREE {
int next, to, dis;
}tree[100010 << 1];
int n, cnt, m, id;
int f[100010][21], df[100010], rdf[100010], deep[100010];
ll d[100010][21];
ll ans;
set <int> s;
int head[100010 << 1];
void ADD(int from, int to, int dis) {
tree[++cnt].next = head[from];
tree[cnt].to = to;
tree[cnt].dis = dis;
head[from] = cnt;
}
void D_F(int son, int fa) {
for(int i = 0; i <= 19; i++) {
f[son][i + 1] = f[f[son][i]][i];
d[son][i + 1] = d[son][i] + d[f[son][i]][i];
}
for(int i = head[son]; i; i = tree[i].next) {
int to = tree[i].to, dis = tree[i].dis;
if(to == fa) continue;
f[to][0] = son;
d[to][0] = dis;
deep[to] = deep[son] + 1;
D_F(to, son);
}
}
ll LCA(int x, int y) {
ll res = 0;
if(deep[x] > deep[y]) swap(x, y);
ll de = deep[y] - deep[x];
for(int i = 0; i <= 20; i++)
if(de & (1 << i))
res += d[y][i], y = f[y][i];
if(x == y) return res;
for(int i = 20; i >= 0; i--) {
if(f[x][i] != f[y][i]) {
res += d[x][i] + d[y][i];
x = f[x][i]; y = f[y][i];
}
}
return res + d[x][0] + d[y][0];
}
void dfs(int now) {
df[now] = ++id;
rdf[id] = now;
for(int i = head[now]; i; i = tree[i].next) {
int to = tree[i].to;
if(!df[to])
dfs(to);
}
}
Int L(Int now) {
if(now == s.begin()) return --s.end();
return --now;
}
Int R(Int now) {
if(now == --s.end()) return s.begin();
return ++now;
}
int main() {
n = sc();
for(int i = 1; i < n; i++) {
int x = sc(), y = sc(), z = sc();
ADD(x, y, z); ADD(y, x, z);
}
D_F(1, 0);
dfs(1);
m = sc();
while(m--) {
char c[2];
cin >> c[0];
if(c[0] == '?') {
printf("%lld\n", (ans >> 1));
}
else if(c[0] == '+') {
int ID = sc();
Int now;
if(s.size()) {
now = s.lower_bound(df[ID]);
if(now == s.end()) now = s.begin();
int first = *L(now);
ans += LCA(ID, rdf[first]) + LCA(ID, rdf[*now]) - LCA(rdf[first], rdf[*now]);
}
s.insert(df[ID]);
}
else if(c[0] == '-') {
int ID = sc();
Int now = s.find(df[ID]);
int first = *L(now);
now = R(now);
ans -= LCA(ID, rdf[first]) + LCA(ID, rdf[*now]) - LCA(rdf[first], rdf[*now]);
s.erase(df[ID]);
}
}
return 0;
}
rp++