P5773 [JSOI2016] 轻重路径
定义
注意到每次删叶子对
删掉
因为每
取
#include <bits/stdc++.h>
#define All(x, l, r) &x[l], &x[r + 1]
#define ALL(x) begin(x), end(x)
using namespace std;
void file(){
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
}
using ll = long long;
const int nMax = 2e5 + 5, Lim = 3503;
int n, q;
array<int, nMax> p, sz, l, r, f, fa, hvy, dif;
array<bool, nMax> lr;
void reb(){
for(int i = n; i; i--) sz[i] = sz[l[i]] + sz[r[i]] + 1;
for(int i = 1; i <= n; i++){
int x = fa[i];
if(abs(dif[i] = sz[l[i]] - sz[r[i]]) <= Lim) x = i;
fa[l[i]] = fa[r[i]] = x;
if(x == i){ lr[l[i]] = 0; lr[r[i]] = 1; }
else lr[l[i]] = lr[r[i]] = lr[i];
}
}
int main(){
// file();
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++){
cin >> l[i] >> r[i];
fa[l[i]] = fa[r[i]] = i;
}
f = fa; cin >> q;
for(int i = 1; i <= q; i++) cin >> p[i];
for(int i = n; i; i--){
sz[i] = sz[l[i]] + sz[r[i]] + 1;
hvy[i] = (sz[l[i]] >= sz[r[i]]) ? l[i] : r[i];
}
ll res = accumulate(All(hvy, 1, n), 0ll);
cout << res << "\n";
for(int i = 1; i <= q; i++){
if(i % 3500 == 1) reb();
int v = p[i], t = f[v]; res -= hvy[v];
(l[t] == p[i]) && (l[t] = 0);
(r[t] == p[i]) && (r[t] = 0);
for(int ls = v, x = fa[v]; x; ls = fa[ls], x = fa[x]){
bool f = lr[ls];
f ? dif[x]++ : dif[x]--;
res -= hvy[x];
if((!dif[x]) && (!l[x]) && (!r[x])) hvy[x] = 0;
if(dif[x] > 0) hvy[x] = l[x];
if(dif[x] < 0) hvy[x] = r[x];
res += hvy[x];
}
cout << res << "\n";
}
return 0;
}