1 条题解

  • 0
    @ 2025-8-24 23:11:31

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar bluewindde
    d2673e765642345244b4fb8edf1add1cf8425a4b7743f39b020d410d67ce15b0

    搬运于2025-08-24 23:11:31,当前版本为作者最后更新于2025-03-28 19:17:42,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    学完 FHQ 三天后这题出现在模拟赛里。


    生成失败就是删点,答案是每个连通块内粒子的个数除以二下取整的和。

    dfnu,lowu\text{dfn}_u, \text{low}_u 表示访问和回溯时的 dfn 序。

    维护每个连通块内的粒子,删点操作就是把粒子分到新产生的连通块内,先减掉原来的贡献,加上新连通块的贡献即可。使用上述 dfn 序 + FHQ-Treap 容易完成该操作。具体而言,设删除点 uu,先把 dfnuxlowu\text{dfn}_u \leqslant x \leqslant \text{low}_uxx 分裂出来,然后用同样方法分裂给 uu 的子树,剩余部分分给原来的连通块根。

    维护每个点属于哪个连通块用线段树容易完成,插入也就容易了。时间复杂度 O(nlogn)O(n \log n)

    #include <chrono>
    #include <iostream>
    #include <random>
    #include <vector>
    
    using namespace std;
    
    namespace particles {
    
    int n;
    vector<int> vec[200005];
    
    int f[200005];
    int dfn[200005], dfn_clock;
    int nfd[200005];
    int low[200005];
    static inline void dfs(int u, int fa) {
        f[u] = fa;
        nfd[dfn[u] = ++dfn_clock] = u;
        for (auto v : vec[u]) {
            if (v == fa)
                continue;
            dfs(v, u);
        }
        low[u] = dfn_clock;
    }
    
    int rt[200005], cnt;
    mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
    struct node {
        int ls, rs, pri, siz, x;
    } tr[200005];
    static inline int make(int x) {
        tr[++cnt].pri = (int)rnd();
        tr[cnt].siz = 1;
        tr[cnt].x = x;
        return cnt;
    }
    static inline void pushup(int p) {
        tr[p].siz = tr[tr[p].ls].siz + tr[tr[p].rs].siz + 1;
    }
    static inline void split(int x, int p, int &u, int &v) {
        if (!p) {
            u = v = 0;
            return;
        }
        if (dfn[tr[p].x] <= x)
            u = p, split(x, tr[p].rs, tr[p].rs, v);
        else
            v = p, split(x, tr[p].ls, u, tr[p].ls);
        pushup(p);
    }
    static inline int merge(int u, int v) {
        if (!u || !v)
            return u | v;
        if (tr[u].pri < tr[v].pri) {
            tr[u].rs = merge(tr[u].rs, v);
            pushup(u);
            return u;
        } else {
            tr[v].ls = merge(u, tr[v].ls);
            pushup(v);
            return v;
        }
    }
    
    int d[800005];
    int tag[800005];
    static inline void pushtag(int p, int c) {
        d[p] = max(d[p], c);
        tag[p] = max(tag[p], c);
    }
    static inline void pushdown(int p) {
        pushtag(p << 1, tag[p]);
        pushtag(p << 1 | 1, tag[p]);
        tag[p] = 0;
    }
    static inline void build(int s, int t, int p) {
        if (s == t) {
            d[p] = 1;
            return;
        }
        int mid = (s + t) >> 1;
        build(s, mid, p << 1);
        build(mid + 1, t, p << 1 | 1);
    }
    static inline void update(int l, int r, int s, int t, int c, int p) {
        if (l <= s && r >= t) {
            pushtag(p, c);
            return;
        }
        int mid = (s + t) >> 1;
        pushdown(p);
        if (l <= mid)
            update(l, r, s, mid, c, p << 1);
        if (r > mid)
            update(l, r, mid + 1, t, c, p << 1 | 1);
    }
    static inline int query(int x, int s, int t, int p) {
        if (s == t)
            return d[p];
        int mid = (s + t) >> 1;
        pushdown(p);
        if (x <= mid)
            return query(x, s, mid, p << 1);
        return query(x, mid + 1, t, p << 1 | 1);
    }
    
    int ans;
    
    static inline void initialize(int _n, const vector<int> &_u, const vector<int> &_v) {
        n = _n;
        for (int i = 0; i < n - 1; ++i) {
            int u = _u[i] + 1, v = _v[i] + 1;
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        dfs(1, 0);
        build(1, n, 1);
    }
    static inline void enable(int u) {
        int r = nfd[query(dfn[u], 1, n, 1)];
        ans -= tr[rt[r]].siz >> 1;
        int x;
        split(dfn[u], rt[r], rt[r], x);
        rt[r] = merge(rt[r], merge(make(u), x));
        ans += tr[rt[r]].siz >> 1;
    }
    static inline void disable(int u) {
        int r = nfd[query(dfn[u], 1, n, 1)];
        ans -= tr[rt[r]].siz >> 1;
        int x, y, z;
        split(dfn[u], rt[r], rt[r], x);
        split(low[u], x, y, z);
        for (auto v : vec[u]) {
            if (v == f[u])
                continue;
            update(dfn[v], low[v], 1, n, dfn[v], 1);
            split(low[v], y, rt[v], y);
            ans += tr[rt[v]].siz >> 1;
        }
        rt[r] = merge(rt[r], z);
        ans += tr[rt[r]].siz >> 1;
    }
    
    } // namespace particles
    
    void initialize(int N, vector<int> A, vector<int> B) {
        particles::initialize(N, A, B);
    }
    int generate(int v, bool result) {
        ++v;
        if (result)
            particles::enable(v);
        else
            particles::disable(v);
        return particles::ans;
    }
    
    • 1

    信息

    ID
    11725
    时间
    5000ms
    内存
    1024MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者