链表+启发式合并
对于每次染色,就将两个颜色合并就行
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int head[maxn], Next[maxn], sum[maxn], col[maxn], now[maxn];
int ans;
inline int read()
{
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ (s *= 10) += ch-'0'; ch = getchar(); }
return s*f;
}
int main()
{
int n, m, x, y, op, last;
n = read(); m = read();
for(int i = 1; i <= n; i++){
col[i] = read();
now[col[i]] = col[i];
sum[col[i]]++;
Next[i] = head[col[i]];
head[col[i]] = i;
if(col[i] != col[i-1]) ans++;
}
for(int i = 1; i <= m; i++){
op = read();
if(op == 2) printf("%d\n",ans);
else{
x = read(); y = read();
if(x == y) continue;
if(sum[now[x]] > sum[now[y]]) swap(now[x],now[y]);
x = now[x]; y = now[y];
if(!sum[x]) continue;
for(int j = head[x]; j; j = Next[j]){
if(col[j-1] == y) ans--;
if(col[j+1] == y) ans--;
last = j;
}
for(int j = head[x]; j; j = Next[j]) col[j] = y;
Next[last] = head[y];
head[y] = head[x];
head[x] = 0;
sum[y] += sum[x];
sum[x] = 0;
}
}
return 0;
}