[HNOI 2009] 梦幻布丁

[题目链接]

        https://www.lydsy.com/JudgeOnline/problem.php?id=1483

[算法]

        链表 + 启发式合并即可

        时间复杂度 : O(NlogN)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define N 1000010
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

int n , m , nowans;
int nxt[N] , head[N] , sz[N] , w[N] , f[N];

template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void read(T &x)
{
   T f = 1; x = 0;
   char c = getchar();
   for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
   for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
   x *= f;
}
inline void merge(int x , int y)
{
    for (int i = head[x]; i; i = nxt[i]) nowans -= (w[i - 1] == y) + (w[i + 1] == y);
    for (int i = head[x]; i; i = nxt[i]) w[i] = y;
    int tail = 0;
    for (int i = head[x]; i; i = nxt[i]) tail = i;
    nxt[tail] = head[y] , head[y] = head[x];
    sz[y] += sz[x];
    head[x] = 0 , sz[x] = 0;
}

int main()
{
    
    read(n); read(m);
    for (int i = 1; i <= n; i++) read(w[i]);
    nowans = unique(w + 1 , w + n + 1) - w - 1;
    for (int i = 1; i <= nowans; i++) 
    {
        nxt[i] = head[w[i]];
        head[w[i]] = i;
        ++sz[w[i]];
        f[w[i]] = w[i];
    }
    for (int i = 1; i <= m; i++)
    {
        int type;
        read(type);
        if (type == 1)
        {
            int x , y;
            read(x); read(y);
            if (x == y) continue;
            if (sz[f[x]] > sz[f[y]]) swap(f[x] , f[y]);
            if (!sz[f[x]]) continue;
            merge(f[x] , f[y]);
        } else printf("%d
" , nowans);
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/10372265.html