N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.
例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.
Input
第一行给出N,M表示布丁的个数和好友的操作次数.
第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,
对于每个操作,
若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y.
若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0。
n,m<=1000000
Output
针对第二类操作即询问,依次输出当前有多少段颜色.
Sample Input
4 3
1 2 2 1
2
1 2 1
2
Sample Output
3 1
bd[ ]当前布丁颜色
color[ ]:某个原来的颜色现在是什么颜色,主要用于在颜色发生交换后识别。
hear tail nxt 链表
size[ ]:颜色数量
当把多的颜色变成少的颜色时,交换颜色,达到优化的目的。启发式合并两个链表。
#include<bits/stdc++.h>
using namespace std;
int bd[1111111],color[1111111],head[1111111],tail[1111111],nxt[1111111],size[1111111];
int ans;
void work(int x,int y)
{
if(x==y)return ;
if(!size[x])return ;//坑啊
size[y]+=size[x];
for(int i=tail[x];i!=-1;i=nxt[i])
{
if(bd[i-1]==y)ans--;
if(bd[i+1]==y)ans--;
//cout<<i<<" "<<color[i-1]<<" "<<color[i+1]<<endl;
}
for(int i=tail[x];i!=-1;i=nxt[i])bd[i]=y;
nxt[head[y]]=tail[x];
head[y]=head[x];
tail[x]=head[x]=-1;
size[x]=0;
}
int main()
{
int n,m;
cin>>n>>m;
ans=0;
memset(tail,-1,sizeof(tail));
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
cin>>bd[i];
if(bd[i]!=bd[i-1])ans++;
color[bd[i]]=bd[i];
if(head[bd[i]]==-1)head[bd[i]]=i;
nxt[i]=tail[bd[i]];
tail[bd[i]]=i;
size[bd[i]]++;
}
int a,b,x,y;
for(int i=0;i<m;i++)
{
cin>>a;
if(a==2)cout<<ans<<endl;
else
{
cin>>x>>y;
if(size[color[x]]>size[color[y]])swap(color[x],color[y]);
work(color[x],color[y]);
}
}
return 0;
}