P8686 洛谷 修改数组
做完这题感觉可以很好地理解并查集。
一眼看过去是不是只看出了暴力(不会只有我这样吧),我们先从暴力的方法再推到并查集方法,首先暴力的做法肯定是:如果一个数有重复的数那就一直加直到没有重复的数。
那这个过程能不能 \(O(1)\) 地求呢,当然可以,对于每个数 \(x\) 将他们的 \(fa[x]\) 一开始设为 \(x\) ,当遍历到这个点时,就将他的 \(fa[x]=x+1\) ,这样操作就可以使下一次遍历到这个点的时候就直接读取 \(fa[x]\) 就相当于 \(O(1)\) 地很好地避免重复增加。
这样一看,这并查集还真有点意思!
#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
int n;
int a[N+5];
int fa[N+5];
int find(int x){
if(fa[x]==x){
return x;
}
return fa[x]=find(fa[x]);
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=N;i++){
fa[i]=i;
}
for(int i=1;i<=n;i++){
int x=find(a[i]);
cout<<x<<" ";
fa[x]++;
}
return 0;
}