CF176E Archaeology

https://www.luogu.com.cn/problem/CF176E

非常重要的一个trick,我竟然不知道

首先把关键点拿出来,按照\(dfs\)序排后为
\(x_1,x_2,x_3,x_4,....,x_k\)
最小联通块大小\(=\frac{1}{2}*(dis(x_1,x_2)+dis(x_2,x_3)+dis(x_3,x_4)+...+dis(x_k,x_1))\)

知道这个之后就可以用set简单维护了

code:

#include<bits/stdc++.h>
#define N 200050
#define ll long long
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
struct edge {
    int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v, int c) {
    e[eid].v = v;
    e[eid].c = c;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
int dfn[N], tot, fa[N][21], dep[N];
ll Dep[N];
void dfs(int u) {
    dfn[u] = ++ tot;
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, c = e[i].c;
        if(v == fa[u][0]) continue;
        fa[v][0] = u, dep[v] = dep[u] + 1;
        Dep[v] = Dep[u] + c;
        dfs(v);
    }
}
int LCA(int x, int y) {
    if(dep[x] < dep[y]) swap(x, y);
    for(int i = 19; i >= 0; i --) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
    if(x == y) return x;
    for(int i = 19; i >= 0; i --) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}
ll dis(int x, int y) {
    return Dep[x] + Dep[y] - 2 * Dep[LCA(x, y)];
}

set<pii > S; 
ll ans = 0;
void del(int x) {
    pii o = make_pair(dfn[x], x);
    auto it = S.lower_bound(o);
    auto ls = it; ls = ls == S.begin() ? -- S.end() : -- ls;
    auto rs = it; rs = rs == -- S.end() ? S.begin() : ++ rs;
    int a = (*ls).se, b = (*rs).se;
 //   printf("%d %d %d   %lld %lld %lld     %d\n", a, b, x, dis(a, x), dis(b, x), dis(a, b), it == S.end());
    ans -= dis(a, x) + dis(x, b) - dis(a, b);
    S.erase(it);
}
void add(int x) {
    pii o = make_pair(dfn[x], x);
    if(!S.size()) {S.insert(o); return ;}
    auto it = S.lower_bound(o);
    auto ls = it; ls = ls == S.begin() ? -- S.end() : -- ls;
    auto rs = it; rs = rs == S.end() ? S.begin() : rs;
    int a = (*ls).se, b = (*rs).se;
  //  printf("%d %d %d   %lld %lld %lld\n", a, b, x, dis(a, x), dis(b, x), dis(a, b));
    ans += dis(a, x) + dis(x, b) - dis(a, b);
    S.insert(o);
}
int n, m;
int main() {
    init();
    scanf("%d", &n);
    for(int i = 1; i < n; i ++) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        insert(u, v, c), insert(v, u, c);
    }

    dfs(1);
    for(int j = 1; j <= 19; j ++)
        for(int i = 1; i <= n; i ++)    
            fa[i][j] = fa[fa[i][j - 1]][j - 1];
    
    // for(int i = 1; i <= n; i ++) printf("%d ", fa[i][1]); printf("\n");
    // for(int i = 1; i <= n; i ++) printf("%lld ", dep[i]); printf("        %d\n", LCA(5, 9));
    scanf("%d", &m);
    while(m --) {
        char c;
        int x;
        scanf(" %c", &c);
        if(c == '?') printf("%lld\n", ans / 2);
        else if(c == '-') {
            scanf("%d", &x);
            del(x);            
        } else {
            scanf("%d", &x);
            add(x);
        }
    }
    return 0;
}
/*
10
7 3 9
8 3 2
10 5 6
9 3 5
2 1 7
7 6 2
3 4 1
7 10 5
10 1 8
11
+ 5
+ 7
+ 2
+ 10
+ 9
+ 8
- 7
+ 3
- 10
- 2
?
*/
posted @ 2021-12-16 20:08  lahlah  阅读(82)  评论(0编辑  收藏  举报