1 条题解

  • 0
    @ 2025-8-24 22:45:05

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 5k_sync_closer
    数据结构真可爱。

    搬运于2025-08-24 22:45:05,当前版本为作者最后更新于2023-02-28 10:51:58,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    谁告诉你 Ynoi 就要手写数据结构了?

    维护 map<int, list<int>> C[N]Ci,jC_{i,j} 表示与 ii 点所在连通块相邻的 jj 色连通块序列。

    axya_x\gets y 时,直接对 CxC_xCiiCx,yC_i|i\in C_{x,y} 启发式合并,然后发现 v\forall vxx 相邻,要更新 Cv,yC_{v,y},假了。

    lxl 说过,这种邻域信息维护父亲一定死,所以令 Ci,jC_{i,j} 表示在 ii 点所在连通块下方的 jj 色连通块序列。

    axya_x\gets y 时,直接对 CxC_xCiiCx,yC_i|i\in C_{x,y} 启发式合并,然后发现只需要更新 Cfax,yC_{\text{fa}_x,y} 了。

    这里没必要从 Cfax,axC_{\text{fa}_x,a_x} 里删掉 xx,启发式合并的时候判断一下是不是真的要合并就行了。

    unordered_map 跑不过 map

    #include <map>
    #include <list>
    #include <cstdio>
    using namespace std;
    struct E
    {
        int v, t;
    } e[1000050];
    map<int, list<int>> C[1000050];
    int n, m, c, a[1000050], s[1000050], f[1000050], g[1000050], h[1000050];
    void A(int u, int v)
    {
        e[++c] = {v, h[u]};
        h[u] = c;
    }
    int F(int x) { return x == f[x] ? x : f[x] = F(f[x]); }
    void L(int u, int v)
    {
        f[v = F(v)] = u = F(u);
        s[u] += s[v];
    }
    void D(int u, int k)
    {
        for (int i = h[u], v; i; i = e[i].t)
            if ((v = e[i].v) != k)
            {
                g[v] = u;
                if (a[v] == a[u])
                    L(u, v);
                else
                    C[F(u)][a[v]].push_back(v);
                D(v, u);
            }
    }
    void M(int x, int y)
    {
        if (C[x].size() < C[y].size())
            swap(C[x], C[y]);
        for (auto i : C[y])
            C[x][i.first].splice(C[x][i.first].end(), i.second);
        C[y].clear();
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 2, x; i <= n; ++i)
            scanf("%d", &x), A(x, i);
        for (int i = 1; i <= n; ++i)
            scanf("%d", a + i), s[f[i] = i] = 1;
        D(1, 0);
        for (int i = 0, o, x, y, z; i < m; ++i)
        {
            scanf("%d%d", &o, &x);
            x = F(x);
            if (o & 1)
            {
                scanf("%d", &y);
                if (a[x] == y)
                    continue;
                auto l = C[x][y];
                for (auto i : l)
                    if (y == a[i] && x != F(i))
                        L(x, i), M(x, i);
                if (y == a[z = F(g[x])])
                    L(z, x), M(z, x);
                else if (z)
                    C[z][y].push_back(x);
                C[F(x)][a[x] = y].clear();
            }
            else
                printf("%d\n", s[x]);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    8373
    时间
    3000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者