多重映射(并查集)

链接:https://ac.nowcoder.com/acm/contest/75771/E
来源:牛客网

已知一个由数字构成的序列 \(A\) ,不妨定义一个函数 \(M(x)=y\) 表示将序列 \(A\) 中全部的数字 \(x\) 都替换为 \(y\) 。例如 \(A=\{2,2,4,5,1,4\}\) ,执行一次\(M(2)=1\) 操作后,序列变为 \(A'=\{1,1,4,5,1,4\}\),很神奇吧!这样的替换显然是能够进行反复叠加的,举例说明,对于上方操作过后的 \(A'\),再执行一次 \(M(1)=2\) 操作,序列会变为 \(A''=\{2,2,4,5,2,4\}\)。现在,给出若干个这样的操作,请你输出修改过后的序列。
输入描述:
每个测试文件均包含多个测试点。第一行输入一个整数 \(T (1\leq T\leq 10^5)\) 代表测试数据组数,每组测试数据描述如下:
第一行输入两个整数 \(n\)\(m(1\leq n, m\leq 10^5)\) 表示序列长度和操作数量。第二行输入 \(n\) 个整数\((1\leq a_i \leq 10^6)\) 表示给定的序列。
此后 \(m\) 行,第 \(i\) 行输入两个整数 \(x_i\)\(y_i(1\leq x_i, y_i\leq 10^6)\) 表示一个操作。保证所有测试用例的 \(n\) 之和不会超过 \(2 \cdot 10^5\)\(m\) 之和不会超过 \(2 \cdot 10^5\)
输出描述:
对于每组数据,你都需要在一行上输出 \(n\) 个整数,代表执行操作后的序列,数字彼此间通过单个空格间隔。

示例1
输入
2
6 1
2 2 4 5 1 4
2 1
6 2
2 2 4 5 1 4
2 1
1 6
输出
1 1 4 5 1 4
6 6 4 5 6 4
说明
该样例已经在题干中加以解释。

示例2
复制
1
3 5
20 17 18
8 16
15 1
20 2
20 1
15 1
输出
2 17 18
备注:

这个题只需要对操作序列倒着想就行,首先我们另vis[i]=i;然后对于操作我们都是vis[x[i]]=vis[y[i]];
比如说操作:
2 1
1 6
倒着想的话就是vis[1]=6,然后vis[2]=vis[1]=6,这样完美的将vis[2]映射成6

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e6+10;
int a[maxn],x[maxn],y[maxn];
int vis[maxn];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
	int t;
	cin>>t;
	for(int i=1;i<maxn;i++){
		vis[i]=i;
	}
	while(t--){
		int n,m;
		cin>>n>>m;
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		for(int i=1;i<=m;i++){
			cin>>x[i]>>y[i];
		}
		for(int i=m;i>=1;i--){
			vis[x[i]]=vis[y[i]];
		}
		for(int i=1;i<=n;i++){
			cout<<vis[a[i]]<<" ";
		}
		cout<<"\n";
		for(int i=1;i<=m;i++){
			vis[x[i]]=x[i];
		}
	}
}
posted @ 2024-03-13 09:31  lipu123  阅读(16)  评论(0)    收藏  举报