并查集+朴素LCA--bzoj4668: 冷战

传送门

边权为时间,是递增的,所以连边不会影响答案,不能路径压缩所以用树高按秩合并,然后每次询问的时候找到两个点到lca的路径上最大值就是答案

#include
#include
#include
#include
#include
#define maxn 500005
using namespace std;
int n,m,fa[maxn],dep[maxn],ans,d[maxn],num,h[maxn];

inline int rd(){
  int x=0,f=1;char c=' ';
  while(c<'0' || c>'9') {if(c=='-')f=-1;c=getchar();}
  while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
  return x*f;
}

inline int find(int x){
  if(x==fa[x]) return x;
  return find(fa[x]);
}

inline void pre(int x){
  if(x==fa[x]) return;
  pre(fa[x]);
  dep[x]=dep[fa[x]]+1;
}

inline int ask(int x,int y){
  pre(x); pre(y);
  if(dep[x]dep[y] && x!=y){
    res=max(res,d[x]);
    x=fa[x];
  }
  while(x!=y){
    res=max(res,max(d[x],d[y]));
    x=fa[x],y=fa[y];
  }
  return res;
}

int main(){
  n=rd(); m=rd();
  for(int i=1;i<=n;i++) fa[i]=i;
  while(m--){
    int ty=rd(),x=rd(),y=rd(); x^=ans; y^=ans;
    if(ty==0){
      num++;
      int u=find(x),v=find(y);
      if(u==v) continue;
      if(h[u]>=h[v]) {
        fa[v]=u,d[v]=num;
        if(h[u]==h[v]) h[u]++;
      }
      else fa[u]=v,d[u]=num;
    }
    else{
      int u=find(x),v=find(y);
      if(u!=v) printf("%d\n",ans=0);
      else printf("%d\n",ans=ask(x,y));
    }
  }
  return 0;
}

 

你可能感兴趣的:(并查集,并查集,LCA)