并查集+启发式合并+LCA思想 || 冷战 || BZOJ 4668

题面:bzoj炸了,以后再补发

题解:

并查集,然后对于每个点记录它与父亲节点联通的时刻 tim ,答案显然是 u 到 v 的路径上最大的 tim 值。启发式合并,把 size 小的子树往大的上并,可以证明树高是 log N 的(我不会),

所以最后套一个LCA思想,直接向上跳着找出路径上最大的 tim 值即为答案,时间复杂度O(N log N)。

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define max(a,b) ((a)>(b)?(a):(b))
 4 using namespace std;
 5 inline int rd(){
 6     int x=0;char c=getchar();
 7     while(c<'0'||c>'9')c=getchar();
 8     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
 9     return x;
10 }
11 const int maxn=5e5+5,maxm=5e5+5;
12 int N,M,o,u,v,ans=0,fa[maxn],tim[maxn],now=0,f1,f2,siz[maxn];
13 int now_tim=0;
14 inline int getf(int n){
15     if(fa[n]==n) return n;
16     return getf(fa[n]);
17 }
18 inline int getdep(int n){
19     int cnt=0;
20     while(fa[n]!=n){
21         cnt++;
22         n=fa[n];
23     }
24     return cnt;
25 }
26 int main(){
27     N=rd(); M=rd();
28     for(int i=1;i<=N;i++) fa[i]=i,siz[i]=1;
29     while(M--){
30         o=rd(); u=rd(); v=rd();
31         u=u^ans; v=v^ans;
32         if(o==0){
33             now_tim++;
34             f1=getf(u); f2=getf(v);
35             if(f1!=f2){
36                 if(siz[f1]>siz[f2]) swap(f1,f2);
37                 siz[f2]+=siz[f1];
38                 fa[f1]=f2;
39                 tim[f1]=now_tim;
40             }
41         }
42         else{
43             f1=getf(u); f2=getf(v);
44             ans=0;
45             if(f1!=f2) {
46                 printf("%d\n",ans);
47                 continue;
48             }
49             int dep1=getdep(u),dep2=getdep(v);
50             if(dep1<dep2) swap(dep1,dep2),swap(u,v);            
51             while(dep1>dep2){
52                 dep1--;
53                 ans=max(ans,tim[u]);
54                 u=fa[u];
55             }
56             if(u!=v){
57                 while(fa[u]!=fa[v]){
58                     ans=max(ans,tim[u]);
59                     ans=max(ans,tim[v]);
60                     u=fa[u]; v=fa[v];
61                 }
62                 ans=max(ans,tim[u]);
63                 ans=max(ans,tim[v]);                
64             }
65             printf("%d\n",ans);
66         }
67     }
68     return 0;
69 }
View Code

 


By:AlenaNuna

 

posted @ 2019-10-04 23:02  AlenaNuna  阅读(181)  评论(0编辑  收藏  举报