用启发式合并来做 复杂度为nlong
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=2e6+10; int head[N],siz[N],pos,c[N],f[N],st[N],ans,n,m; int nex[N]; struct Edge{int to,nex;}edge[N<<1]; void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;} int Merge(int x,int y) { for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; ans-=(y==c[v-1])+(y==c[v+1]); } for(int i=head[x];i;i=edge[i].nex)c[edge[i].to]=y; edge[st[x]].nex=head[y];head[y]=head[x];siz[y]+=siz[x]; head[x]=siz[x]=st[x]=0; } int main() { scanf("%d%d",&n,&m); rep(i,1,n) { scanf("%d",&c[i]);f[c[i]]=c[i]; ans+=c[i]!=c[i-1]; if(!head[c[i]])st[c[i]]=pos+1; siz[c[i]]++;add(c[i],i); } while(m--) { int op;scanf("%d",&op); if(op==2)printf("%d\n",ans); else { int x,y;scanf("%d%d",&x,&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]); } } }