[BZOJ4668]冷战:并查集+启发式合并

分析:

用并查集维护一个边权为时间的最小生成树,为了减小树高需要按秩合并。
其实想要达到O(nlogn)复杂度树剖+ST表或LCT都行......

代码:

贴个别人的博客,我实在是不想写了:https://blog.csdn.net/just_sort/article/details/52253481

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 500010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
int f[MAXN],h[MAXN],v[MAXN],dep[MAXN];
int la;
int T;
int n,m;
int fa(int x){
    return f[x]==x?x:fa(f[x]);
}
void pre(int x){
    if(f[x]==x){
        return ;
    }
    pre(f[x]);
    dep[x]=dep[f[x]]+1;
}
int ask(int x,int y){
    pre(x);
    pre(y);
    if(dep[x]<dep[y]){
        swap(x,y);
    }
    int re=0;
    while(dep[x]>dep[y]&&x!=y){
        re=max(re,v[x]);
        x=f[x];
    }
    while(x!=y){
        re=max(re,max(v[x],v[y]));
        x=f[x];
        y=f[y];
    }
    return re;
}
int main(){
    int i,o,x,y;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        f[i]=i;
    }
    while(m--){
        scanf("%d%d%d",&o,&x,&y);
        x^=la;
        y^=la;
        if(o==0){
            int fx=fa(x),fy=fa(y);
            T++;
            if(fx!=fy){
                if(h[fx]<=h[fy]){
                    f[fx]=fy;
                    v[fx]=T;
                    if(h[fx]==h[fy]){
                        h[fy]++;
                    }
                }else{
                    f[fy]=fx;
                    v[fy]=T;
                }
            }
        }
        if(o==1){
            int fx=fa(x),fy=fa(y);
            if(fx!=fy){
                printf("%d\n",la=0);
            }else{
                printf("%d\n",la=ask(x,y));
            }
        }
    }
    return 0;
}
 
/*
*/

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9490268.html