【刷题笔记】p10930 异象石
思路
首先注意到一个非常难注意到的性质:
将所有有异象石的点按时间戳进行排序,算出每个 \(a_i,a_{i+1}\) 在树上的最短路径和 \(a_n,a_1\) 在树上的最短路径的和,这个和就是第三种询问答案的二倍。
维护一个 set。
若加入 x 号点,它在 set 中左边的点是 l,右边是 r。则在加入时,断开 l->r,加入 l->x 与 x->r。
若删除 x 号点,同理,断开 l->x 与 x->r,加入 l->r。
#include<bits/stdc++.h>
#define N 100010
#define INF 2147483647
#define int long long
using namespace std;
int n, cnt = 0, head[N], q;
int dep[N], d[N], f[N][30], dfn[N], tim = 0, Dfs[N], ans = 0;
set<int>st;
struct edge{
int to, next, w;
}e[N << 2];
void add(int x, int y, int w){
e[++cnt].to = y;
e[cnt].w = w;
e[cnt].next = head[x];
head[x] = cnt;
}
void dfs(int u, int fa){
dfn[u] = ++tim, Dfs[tim] = u;
f[u][0] = fa, dep[u] = dep[fa] + 1;
for(int i = 1; i <= 20; i++){
f[u][i] = f[f[u][i - 1]][i - 1];
}
for(int i = head[u]; i; i = e[i].next){
int v = e[i].to, w = e[i].w;
if(v == fa) continue;
d[v] = d[u] + w;
dfs(v, u);
}
}
int Lca(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
int len = dep[x] - dep[y];
for(int i = 0; i <= 20; i++){
if(len & 1) x = f[x][i];
len >>= 1;
}
if(x == y) return x;
for(int i = 20; i >= 0; i--){
if(f[x][i] != f[y][i])
x = f[x][i], y = f[y][i];
}
return f[x][0];
}
int calc(int x, int y){
return d[x] + d[y] - 2 * d[Lca(x, y)];
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n;
int x, y, w;
for(int i = 1; i < n; i++){
cin >> x >> y >> w;
add(x, y, w), add(y, x, w);
}
dfs(1, 0); st.insert(-INF), st.insert(INF);
cin >> q;
while(q--){
char op; int x;
cin >> op;
if(op == '+'){
cin >> x;
auto it = st.lower_bound(dfn[x]);
int r = *it, l = *(--it);
if(l != -INF) ans += calc(Dfs[l], x);
if(r != INF) ans += calc(x, Dfs[r]);
if(l != -INF && r != INF) ans -= calc(Dfs[l], Dfs[r]);
st.insert(dfn[x]);
}
if(op == '-'){
cin >> x;
st.erase(dfn[x]);
auto it = st.lower_bound(dfn[x]);
int r = *it, l = *(--it);
if(l != -INF) ans -= calc(Dfs[l], x);
if(r != INF) ans -= calc(x, Dfs[r]);
if(l != -INF && r != INF) ans += calc(Dfs[l], Dfs[r]);
}
if(op == '?'){
if(st.size() <= 3) cout << 0 << endl;
else cout << (ans + calc(Dfs[*st.upper_bound(-INF)], Dfs[*(--st.lower_bound(INF))])) / 2 << endl;
}
}
return 0;
}

浙公网安备 33010602011771号