《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;
}
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/13917557.html