Bootstrap

[ABC329F] Colored Ball(启发式合并模板)

[ABC329F] Colored Ball

题面翻译

给定 N N N 个盒子,每个盒子里面有一个颜色为 C i C_i Ci 的小球。有 Q Q Q 次操作,每次操作将第 a i a_i ai 个盒子中的球都放到第 b i b_i bi 个盒子里面,你需要在每次操作后输出当前操作结束后第 b i b_i bi 个盒子里面有多少个不同颜色的小球。

如果盒子为空,输出 0 0 0 即可。

输入格式

入力は以下の形式で標準入力から与えられる。ここで、 $ \text{query}_i $ は $ i $ 番目のクエリを意味する。

$ N $ $ Q $ $ C_1 $ $ C_2 $ $ \ldots $ $ C_N $ $ \text{query}_1 $ $ \text{query}_2 $ $ \vdots $ $ \text{query}_Q $

各クエリは次の形式で与えられる。

$ a $ $ b $

输出格式

$ Q $ 行出力せよ。 $ i $ 行目には $ i $ 番目のクエリに対する答えを出力せよ。

样例 #1

样例输入 #1

6 5
1 1 1 2 2 3
1 2
6 4
5 1
3 6
4 6

样例输出 #1

1
2
1
1
3

样例 #2

样例输入 #2

5 3
2 4 2 4 2
3 1
2 5
3 2

样例输出 #2

1
2
0

启发式合并:让小的并到大的上面

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll>PII;
typedef pair<ll, string>PIS;
const int N = 2e5 + 10;
const int MOD = 998244353;
const int INF = 0X3F3F3F3F;
const int dx[] = {-1, 1, 0, 0, -1, -1, +1, +1};
const int dy[] = {0, 0, -1, 1, -1, +1, -1, +1};
const int M = 1e9 + 7;

ll a[N];
ll p[N];
set<ll>se[N];

ll finds(ll x)
{
	if(x != p[x]) p[x] = finds(p[x]);
	return p[x];
}
int main()
{
	int n, q;
	cin >> n >> q;
	for(int i = 1; i <= n; i ++)
	{
	    cin >> a[i];
		se[i].insert(a[i]);
	}
	//启发式合并:优先遍历更小的数组
	while(q --){
		ll l, r;
		cin >> l >> r;
		if(se[l].size() < se[r].size())
		{
			for(auto it : se[l])
			{
				se[r].insert(it);
			}
			se[l].clear();
		}
	    else {
			for(auto it : se[r])
			{
				se[l].insert(it);
			}
			se[r].clear();
			swap(se[r], se[l]);
		}
		cout << se[r].size() << endl;
	}
	return 0;
}
;