[HNOI2009]梦幻布丁
[HNOI2009]梦幻布丁
给每个颜色的点挂个链.按size启发式暴力合并.
如果一个联通的色块左边或者右边等于要变的颜色,那么色块总数减一.这样维护答案就好了.
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
int head[maxn],nxt[maxn],n,m,ans,cor[maxn],sz[maxn],ori[maxn];
void merge(int &x,int &y)
{
if(x==y)return;
if(sz[x]>sz[y])swap(x,y);
for(int i=head[x];i;i=nxt[i])
{
ans-=(cor[i-1]==y)+(cor[i+1]==y);
if(!nxt[i]){nxt[i]=head[y],head[y]=head[x];break;}
}
for(int i=head[x];i;i=nxt[i])cor[i]=y;
sz[y]+=sz[x];sz[x]=0;head[x]=0;
}
int main()
{
cin>>n>>m;int ty,x,y;
for(int i=1;i<=n;i++)
scanf("%d",&cor[i]),nxt[i]=head[cor[i]],head[cor[i]]=i,sz[cor[i]]++;
for(int i=1;i<=maxn-5;i++)ori[i]=i;
ans=1;for(int i=2;i<=n;i++)if(cor[i]!=cor[i-1])ans++;
for(int i=1;i<=m;i++)
{
scanf("%d",&ty);
if(ty==1)scanf("%d%d",&x,&y),merge(ori[x],ori[y]);
else printf("%d\n",ans);
}
return 0;
}