BZOJ1483——链表

点击看题

这题其实可以用链表随意乱搞……

将每个颜色做成一个链表(然而可以不用指针),链表里面存这些颜色的起始点、终止点、前继点、个数等信息

然后变颜色时就用启发式合并,将少的颜色接在多的颜色后面就可以了

……吗?

并不是,比如说我把颜色1染成颜色2,但是颜色2的个数小于颜色1的个数的话,那么颜色2接在颜色1后面。但是如果接下来找颜色2的链表时,它就不见了……

因此我们要加开一个belong数组,belong[x]=y表示颜色y的链表在x处,在启发式合并时如果把颜色a染成颜色b后面但是size[b]<size[a]的话,就交换belong[a]和belong[b],初始化时belong[x]=x

好了,代码如下:

#include<stdio.h>
#include<math.h>
#include<algorithm>
#define N 1001000
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define repu(i,r,l) for(int i=r;i>=l;i++)
using namespace std;
int n,m,ans,belong[N],c[N],st[N],en[N],pre[N],size[N];
void change(int x,int y)
{
	if (size[belong[x]]>size[belong[y]]) swap(belong[x],belong[y]);
	if (size[belong[x]]==0) return;
	x=belong[x],y=belong[y];
	for (int i=en[x];i;i=pre[i])
	{
		if (c[i-1]==y) ans--;
		if (y==c[i+1]) ans--;
	}
	for (int i=en[x];i;i=pre[i]) c[i]=y;
	size[y]+=size[x],size[x]=0;
	pre[st[x]]=en[y];
	en[y]=en[x];
	st[x]=en[x]=size[x]=0;
}
int main()
{
	scanf("%d%d",&n,&m);
	rep(i,1,n)
	{
		scanf("%d",&c[i]);
		belong[c[i]]=c[i];
		size[c[i]]++;
		if (c[i]!=c[i-1]) ans++;
		if (!st[c[i]]) st[c[i]]=i;
		pre[i]=en[c[i]];en[c[i]]=i;
	}
	rep(i,1,m)
	{
		int typ,x,y;
		scanf("%d",&typ);
		if (typ==2) printf("%d\n",ans);
		else
		{
			scanf("%d%d",&x,&y);
			if (x==y) continue;
			change(x,y);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值