前言
传送门 : https://atcoder.jp/contests/abc183/tasks/abc183_f
思路
本题需要求的是
- 将两个 x 和 y 合并到一个集合中
- 将 计算 在x所属集合中 和 y 同一个班级的个数
第一个 : 不就是裸并查集吗
第二个 : 一开始以为只是简单的 维护 集合内的个数
但是没想到还给集合分了类,因此我们一开始想到的是二维数组
(二维数组给每一个类都记一下 )
但是呢 这题数据不好开 所以我们可以 用map来处理
这样子我们就不用每个集合都开了 ,我们只需要维护当前集合中班级的情况
既然是用map存放了,我们就想到了 按秩合并
因此这题就顺着写下来了
CODE
#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
const int N = 2e5+10;
int p[N];
cc_hash_table<int,int>::iterator it;
int find(int x)
{
if(x!=p[x])return p[x] = find(p[x]);
return p[x];
}
void solve()
{
int n,q;
cin>>n>>q;
cc_hash_table<int,cc_hash_table<int,int>> mp;
for(int i=1; i<=n; i++)
{
int x;
cin>>x;
mp[i][x] = 1;
p[i] = i;
}
while(q -- )
{
int op,x,y;
cin>>op>>x>>y;
if(op == 1)
{
/**按秩合并**/
int fa = find(x);
int fb = find(y);
if(fa!=fb)
{
if(mp[fa].size()>mp[fb].size())
swap(fa,fb);
p[fa] =fb;
for(it = mp[fa].begin(); it!=mp[fa].end(); it++)
{
mp[fb][it->first] +=it->second;
}
}
}
else
{
int fa =find(x);
if(mp[fa].find(y) != mp[fa].end())
{
cout<<mp[fa][y]<<endl;
}
else
{
cout<<0<<endl;
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
solve();
return 0;
}