链表的启发式合并
O(nlogn)
直接拿seter(233333)水多好
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100000+5;
const int M=1000000+5;
int head[M],next[N],ans,c[N],fa[M],sz[M];
void merge(int u,int v){
for(int i=head[u];i;i=next[i])
ans-=(c[i-1]==v)+(c[i+1]==v);
for(int i=head[u];i;i=next[i])c[i]=v;
for(int i=head[u];i;i=next[i])if(!next[i]){next[i]=head[v];break;}
head[v]=head[u];sz[v]+=sz[u];
head[u]=sz[u]=0;
}
int main(){
//freopen("a.in","r",stdin);
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&c[i]);fa[c[i]]=c[i];
if(c[i]!=c[i-1])ans++;
next[i]=head[c[i]];head[c[i]]=i;sz[c[i]]++;
}
int opt,x,y;
while(m--){
scanf("%d",&opt);
if(opt==1){
scanf("%d%d",&x,&y);
if(x==y)continue;
if(sz[fa[x]]>sz[fa[y]])swap(fa[x],fa[y]);
x=fa[x];y=fa[y];
if(!sz[x])continue;
merge(x,y);
}else printf("%d\n",ans);
}
return 0;
}