P8686 洛谷 修改数组

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; 
}
posted @ 2024-08-27 20:33  sad_lin  阅读(37)  评论(0)    收藏  举报