蓝桥杯 2026 省 Python B 组 蓝小圈 题解 —— 并查集 启发式合并
· 4 min read
P16265 [蓝桥杯 2026 省 Python B 组] 蓝小圈 - 洛谷
当我们需要不断合并两个集合时,如果每次都把元素较少的集合合并到元素较多的集合,那么每个元素被移动的次数不会超过 O(logn) 次。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using db = double;
#define dbg(x) cerr << #x << " = " << (x) << endl;
#define vdbg(a) cout << #a << " = "; for (auto x : a) cout << x << " "; cout << endl;
#define int long long
const int N = 2e5;
vector<int> w(N + 1), a(N + 1);
struct DSU {
vector<int> fa;
vector<vector<int>> g;
DSU (int n) {
fa.resize(n);
g.resize(n);
for (int i = 0; i < n; ++i) {
fa[i] = i;
g[i].push_back(i);
}
}
int find (int x) {
if (fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
void unite(int x, int y) {
int rx = find(x), ry = find(y);
if (rx == ry) return;
if (g[rx].size() > g[ry].size()) swap(rx, ry);
for (int u : g[rx]) {
a[u] += w[rx] - w[ry];
g[ry].push_back(u);
}
w[rx] = 0;
g[rx].clear();
fa[rx] = ry;
}
};
void solve() {
int n, q; cin >> n >> q;
DSU t(n + 1);
while (q--) {
int op, x, y;
cin >> op >> x;
if (op == 1) {
cin >> y;
t.unite(x, y);
}
else if (op == 2) {
cin >> y;
a[x] += y;
}
else if (op == 3) {
cin >> y;
w[t.find(x)] += y;
}
else {
cout << a[x] + w[t.find(x)] << "\n";
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}