因为启发式合并,所以我们强制用长链代表短链,遍历修改短链的所有节点
由于我们只存储了位置之间是同色的关系形成的链条,这些链条无颜色特征,所以我们把长链分配给新颜色
即一次swap操作,用fa[x]记录颜色x的在C数组中存储的真实颜色
其他部分就是水水细节啦。。
#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
using namespace std;
#define ll long long
const int maxn=1e6+7;
const int inf=0x3f3f3f3f;
#define FOR(n) for(int i=1;i<=n;i++)
#define pb push_back
int n,m,ans;
int c[maxn],fa[maxn];
int size[maxn],head[maxn],nxt[maxn];
void merge(int x,int y){
for(int i=head[x];i;i=nxt[i]){
if(c[i-1]==y)ans--;
if(c[i+1]==y)ans--;
}
for(int i=head[x];i;i=nxt[i]){
c[i]=y;
if(!nxt[i]){
nxt[i]=head[y],head[y]=head[x];break;
}
}
size[y]+=size[x];head[x]=size[x]=0;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&c[i]);
if(c[i]!=c[i-1])ans++;
fa[c[i]]=c[i];
nxt[i]=head[c[i]],head[c[i]]=i;
size[c[i]]++;
}
for(int op,x,y,i=1;i<=m;i++){
scanf("%d",&op);
if(op==2)printf("%d\n",ans);
else{
scanf("%d%d",&x,&y); // x染色为y
if(size[fa[x]]>size[fa[y]])swap(fa[x],fa[y]);
x=fa[x],y=fa[y];
if(x==y || size[x]==0)continue;
merge(x,y);
}
}
}