《hdu2818》
蛮经典的带权并查集问题。
一开始向顶上维护从上往下的排名但是wa了,不知道为什么。
后面改成向下维护了。因为对于堆底,它的ans都是0,然后在路径压缩时更新即可。
这里有两个细节,首先路径压缩不会重复去加,因为一次合并之后fa[x]就是堆底了,且堆底的ans = 0,这样之后加的都是0了。
第二就是要先记录pre再去find再更新,这样其实是先更新了pre的值再用更新的pre的值再去更新x。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 2e5+5; const int M = 1e6+5; const LL Mod = 200907; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int fa[N],sz[N],ans[N]; int Find(int x) { if(x == fa[x]) return x; else { int pre = fa[x]; fa[x] = Find(fa[x]); ans[x] += ans[pre]; return fa[x]; } } int main() { CT0;IO; int n;cin >> n; for(int i = 0;i < N;++i) fa[i] = i,sz[i] = 1,ans[i] = 0; while(n--) { char c;cin >> c; if(c == 'M') { int x,y;cin >> x >> y; int px = Find(x),py = Find(y); if(px == py) continue; fa[px] = py; ans[px] = sz[py]; sz[py] += sz[px]; } else { int x;cin >> x; int xx = Find(x);//路径压缩更新 cout << ans[x] << endl; } } system("pause"); return 0; }