• 洛谷 P3201 [HNOI2009]梦幻布丁(启发式合并)


    题面

    luogu

    题解

    • 什么是启发式合并?
      小的合并到大的上面
      复杂度(O(nlogn))

    这题颜色的修改,即是两个序列的合并

    考虑记录每个序列的(size)

    小的合并到大的

    存序列用链表

    但是有一种情况,
    (x->y)
    (siz[x] > siz[y])

    这个时候我们可以新建一个(f)数组,存一个真实颜色

    碰到这种情况时,(swap(f[x], f[y]))

    合并即是(f[x]->f[y])

    Code

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    
    #define LL long long
    #define RG register
    
    using namespace std;
    template<class T> inline void read(T &x) {
        x = 0; RG char c = getchar(); bool f = 0;
        while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
        while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
        x = f ? -x : x;
        return ;
    }
    template<class T> inline void write(T x) {
        if (!x) {putchar(48);return ;}
        if (x < 0) x = -x, putchar('-');
        int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
        for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
    }
    
    const int N = 1e6+10;
    
    int c[N], ans;
    
    int f[N], nxt[N], last[N], st[N], siz[N];
    
    void merge(int x, int y) {//x合并到y上 
        for (int i = last[x]; i; i = nxt[i]) ans -= (c[i-1] == y) + (c[i+1] == y);
        for (int i = last[x]; i; i = nxt[i]) c[i] = y;
        nxt[st[x]] = last[y], last[y] = last[x], siz[y] += siz[x];
        last[x] = siz[x] = st[x] = 0;
    }
    
    int main() {
        int n, m;
        read(n), read(m);
        for (int i = 1; i <= n; i++) {
            read(c[i]);
            ans += c[i] != c[i-1];
            if (!last[c[i]]) st[c[i]] = i, f[c[i]] = c[i];
            nxt[i] = last[c[i]], last[c[i]] = i, siz[c[i]]++; 
        }
        while (m--) {
            int opt; read(opt);
            if (opt == 2) printf("%d
    ", ans);
            else {
                int x, y;
                read(x), read(y);
                if (x == y) continue;
                if (siz[f[x]] > siz[f[y]]) swap(f[x], f[y]);
                if (!siz[f[x]]) continue;
                merge(f[x], f[y]); 
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    sizeof--返回一个数据类型或变量占用的字节数
    跳出循环break continue
    c-for循环
    while循环语句
    什么是Python中的套接字编程?
    详解Vue八大生命周期钩子函数
    你应该知道的数仓安全
    云图说|华为云自研云数据库GaussDB NoSQL,兼容多款NoSQL接口的数据库服务
    又到一年“粽子节”,快来测测你包的粽子颜值几分
    云小课 | 华为云KYON之私网NAT网关
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10328681.html
Copyright © 2020-2023  润新知