zoukankan      html  css  js  c++  java
  • 洛谷 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;
    }
    
    
  • 相关阅读:
    把联系人从一张卡转移到另一张卡或者从一个手机转移到另一个手机
    Echarts画折线图
    Echarts画条形图
    Echarts画饼状图
    《计算机网络》读后感
    Vue.js项目无法启动:sh: 1: vue-cli-service: not found
    《Redis入门指南(第 2 版)》读后感
    翻译:《实用的Python编程》InstructorNotes
    翻译:《实用的Python编程》TheEnd
    翻译:《实用的Python编程》09_03_Distribution
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10328681.html
Copyright © 2011-2022 走看看