启发式合并

启发式合并

即:玄学合并

P3012 梦幻布丁


#include<bits/stdc++.h>
using namespace std;

const int N=1e5+5,M=1e6+5;
int n,m,ans,a[N],st[M],f[M],pre[M],tail[M],siz[M];

void union_(int x,int y)
{
	for(int i=tail[x];i;i=pre[i]) ans-=(a[i+1]==y)+(a[i-1]==y);
	for(int i=tail[x];i;i=pre[i]) a[i]=y;
	
	pre[st[x]]=tail[y],tail[y]=tail[x],siz[y]+=siz[x];
	st[x]=tail[x]=siz[x]=0;
}

int main()
{
	scanf("%d %d",&n,&m);
	
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&a[i]);
		ans+=a[i]!=a[i-1];
		if(!st[a[i]]) f[a[i]]=a[i],st[a[i]]=i;
		pre[i]=tail[a[i]],tail[a[i]]=i,siz[a[i]]++;
	}
	
	for(int i=1,op,x,y;i<=m;++i)
	{
		scanf("%d",&op);
		
		if(op==2) printf("%d\n",ans);
		else
		{
			scanf("%d %d",&x,&y);
			if(x==y) continue;
			//y存在,取siz小的进行染色
            //y不存在,直接将对应的颜色交换,则x会对应为一个不存在的颜色,siz必定为0,这个时候无需重新染色,直接判断然后跳过
			if(siz[f[x]]>siz[f[y]]) swap(f[x],f[y]);
			
			if(!siz[f[x]]) continue;
			
			union_(f[x],f[y]);
		}
	}
	
}
posted @ 2020-10-23 20:48  林生。  阅读(88)  评论(0)    收藏  举报