[BZOJ4668]冷战

题目大意:
  一个$n(n\le5\times10^5)$个点的图,初始时没有边,有$m(m\le5\times10^5)$次操作,操作包含以下两种:
    1.在$u,v$之间连一条无向边;
    2.询问$u,v$经过几次操作1之后连通。

思路:
  并查集按秩合并,不路径压缩。询问时暴力LCA求路径最大值。时间复杂度$O(m\log n)$。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 };
11 const int N=500001;
12 int par[N],w[N],h[N],dep[N];
13 int find(const int &x) {
14     if(par[x]==x) return x;
15     const int ret=find(par[x]);
16     dep[x]=dep[par[x]]+1;
17     return ret;
18 }
19 inline int query(int u,int v) {
20     int ret=0;
21     while(u!=v) {
22         if(dep[u]<dep[v]) std::swap(u,v);
23         ret=std::max(ret,w[u]);
24         u=par[u];
25     }
26     return ret;
27 }
28 int main() {
29     const int n=getint();
30     for(register int i=1;i<=n;i++) h[par[i]=i]=1;
31     for(register int m=getint(),ans=0,cnt=0;m;m--) {
32         const int opt=getint(),u=getint()^ans,v=getint()^ans;
33         if(opt==0) {
34             int x=find(u),y=find(v);
35             if(h[x]>h[y]) std::swap(x,y);
36             h[par[x]=y]=std::max(h[y],h[x]+1);
37             w[x]=++cnt;
38         }
39         if(opt==1) printf("%d\n",ans=find(u)!=find(v)?0:query(u,v));
40     }
41     return 0;
42 }

 

posted @ 2018-03-22 16:10  skylee03  阅读(92)  评论(0编辑  收藏  举报