启发式合并
很牛的一个思想,而且很简单
这里只推荐一道好题: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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】