启发式合并

很牛的一个思想,而且很简单

这里只推荐一道好题P3201 [HNOI2009] 梦幻布丁。因为题解讲得非常好,建议先自己想想,没学的先学。

提供两个 hack。

hack1:
7 5
5 7 8 2 4 8 7 
1 5 8
1 7 4
2
1 4 2
2


update1:8 7 8 2 4 8 7
update2:8 4 8 2 4 8 4
update3:8 2 8 2 2 8 2

---

hack2(60pts):
7 3
6 8 6 3 2 1 6 
1 2 7
1 2 3
2
update1:6 8 6 3 7 1 6
update2:6 8 6 3 7 1 6

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5, element =1e6+5;
int n,m,a[N],sum,fa[element],siz[element];
vector<int> col[element];
inline int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
	return s*f;
}
void merge(int x,int y){
	for(int i=0;i<siz[x];i++){
		int seat=col[x][i];
		sum-=(a[seat-1]==y)+(a[seat+1]==y);
	}
	for(int i=0;i<siz[x];i++)a[col[x][i]]=y,col[y].push_back(col[x][i]);
	siz[y]+=siz[x];siz[x]=0;
	col[x].clear();
}
int main(){
	n=read();m=read();
	for(int i=1;i<=element-5;i++)fa[i]=i;
	for(int i=1;i<=n;i++)a[i]=read(),col[a[i]].push_back(i),siz[a[i]]++,sum+=(a[i]!=a[i-1]);//a[0]与a[1]肯定不同
	while(m--){
		int opt=read();
		if(opt==1){
			int x=read(),y=read();
			if(x==y)continue;
			if(siz[fa[x]]>siz[fa[y]])swap(fa[x],fa[y]);
			if(!siz[fa[x]])continue;
			merge(fa[x],fa[y]);
		}else cout<<sum<<endl;
	} 
	return 0;
}
posted @   今添  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示