1459: [蓝桥杯2019初赛]修改数组(巧用并查集)

ぃ、小莉子 提交于 2020-02-22 20:55:05

题目链接:点击这里
在这里插入图片描述
在这里插入图片描述

vis数组标记判重,通过80%

数组元素全部相同时,时间复杂度为 O(n(n1)2)O(\frac{n(n-1)}{2}),超时:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int a[100010];
bool vis[1000010];

int main()
{
	int n;
	scanf("%d", &n);
	
	for(int i = 1; i <= n; ++i)
		scanf("%d", &a[i]);
	
	vis[a[1]] = true;
	for(int i = 2; i <= n; ++i)
	{
		while(vis[a[i]])
		{
			a[i]++;
		}
		vis[a[i]] = true;
	}
	
	for(int i = 1; i <= n; ++i)
		printf("%d ", a[i]);
	
	return 0;
}

搜题解:

这题可以巧妙地利用并查集。 我们初始化 ii 的父亲为 ii,然后依次遍历输入的数组,使 a[i]=find(a[i])a[i] = find(a[i]),再令 f[a[i]]=find(a[i]+1)f[a[i]] = find(a[i]+1) 即可。

假如数组为 1,2,11, 2, 1

  1. 第一次输入 11a[1]=find(a[1])=find(1)=1a[1] = find(a[1]) = find(1) = 1,更新 f[a[1]]=f[1]=find(a[1]+1)=find(2)=2f[a[1]] = f[1] = find(a[1]+1) = find(2) = 2

  2. 第二次输入 22a[2]=find(a[2])=find(2)=2a[2] = find(a[2]) = find(2) = 2,更新 f[a[2]]=f[2]=find(a[2]+1)=find(3)=3f[a[2]] = f[2] = find(a[2]+1) = find(3) = 3

  3. 第三次再输入 11a[3]=find(a[3])=find(1)=find(2)=3a[3] = find(a[3]) = find(1) = find(2) = 3, 这时候 a[3]a[3] 便等于 33 了。

这种查询的时间复杂度仅为 O(logn)O( logn)。整体时间复杂度 O(nlognlogn)O(n*logn*logn)

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6+10;

int a[maxn], f[maxn];

int find(int x)
{
	if(f[x]==x)	return x;
	else	return f[x] = find(f[x]);
}

int main()
{
	for(int i = 1; i <= maxn; i++)		//初始化f数组为它本身 
		f[i] = i;
	
	int n;
	scanf("%d", &n);
	
	for(int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
		a[i] = find(a[i]);				//直接把这个数变成他的父亲 
		f[a[i]] = find(a[i]+1);
	}
	
	for(int i = 1; i <= n; ++i)
		printf("%d ", a[i]);
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!