启发式合并

启发式合并听起来挺高端,但好像只是一种基础的合并思想(?)

将小的集合中的数都加到大的集合中去,一般用一个map进行维护

一.并查集与启发式合并

1.[ABC183F] Confluence

#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;

const int N = 2e5 + 10;
int pre[N], a[N];
map<int, int> mp[N];//第i个学生的小组中,j班学生的个数

int root(int x){
	return pre[x] = (pre[x] == x ? x : root(pre[x]));
}
void merge(int u, int v){
	pre[root(u)] = root(v);
}
bool isCon(int u, int v){
	return root(u) == root(v);
}


void solve() {
	int n, q; cin >> n >> q;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		pre[i] = i;
		mp[i][a[i]] = 1;
	}
	while(q--){
		int op, x, y; cin >> op >> x >> y;
		if(op == 1){
			int xx = root(x), yy = root(y);
			if(xx == yy) continue;
			if(mp[xx].size() > mp[yy].size()) swap(xx, yy);
			for(pair<int, int> i : mp[xx]){
				mp[xx][i.first] = 0, mp[yy][i.first] += i.second;
			}
			pre[xx] = yy;
		}else{
			cout << mp[root(x)][y] << '\n';
		}
	}
}


signed main() {
	qio
	int T = 1;
//	cin >> T;
	while (T--)	solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值