bzoj 4668 冷战 Posted on 2019-05-22 | Views: 并查集按秩合并. 除了维护连通性,还需要维护每个点与它父亲的边被连上的时间. 用路径压缩会破坏树内部的结构,使用按秩合并就可以了.这样合并,树高不超过 $logn$ ,询问时,直接暴力跳到 $LCA$ ,路径上边被连上的最晚时间即为答案. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=5e5+10;int n,m,lastans=0;int fa[MAXN],siz[MAXN],t[MAXN],dep[MAXN],tid=0;int Find(int x){ if(x==fa[x]) return x; int fx=Find(fa[x]); dep[x]=dep[fa[x]]+1; return fx;}void merge(int x,int y){ x=Find(x),y=Find(y); if(x==y) return; if(siz[x]<siz[y]) swap(x,y); siz[x]+=siz[y]; fa[y]=x; t[y]=tid;}int query(int x,int y){ int fx=Find(x),fy=Find(y); if(fx!=fy) return 0; int res=0; while(x!=y) { if(dep[x]<dep[y]) swap(x,y); res=max(res,t[x]); x=fa[x]; } return res;}int main(){ n=read(),m=read(); for(int i=1;i<=n;++i) siz[i]=1,fa[i]=i; for(int i=1;i<=m;++i) { int tp=read(); if(!tp) { int u=read()^lastans,v=read()^lastans; ++tid; merge(u,v); } else { int u=read()^lastans,v=read()^lastans; lastans=query(u,v); printf("%d\n",lastans); } } return 0;}