[loj6038]「雅礼集训 2017 Day5」远行 lct+并查集

给你 n 个点,支持 m 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林;询问一个点能到达的最远的点与该点的距离。强制在线。

n3×10^n≤3×10^5 ,m5×10^m≤5×10^5 。


我们知道与一个点距离最大的点为任意一个直径的两个端点之一。

两棵树之间连一条边,新树直径的两个端点一定为第一棵树直径的两个端点和第二棵树直径的两个端点这四者中之二。

于是我们可以用lct和并查集来维护树的直径的两个端点。

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #define fa(x) t[x].fa
 8 #define s(x,y) t[x].son[y]
 9 #define maxn 305050
10 using namespace std;
11 inline int read() {
12     int x=0,f=1;char ch=getchar();
13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
15     return x*f;
16 }
17 int type;
18 int n,q;
19 struct LCT {
20     int f[maxn],px[maxn],py[maxn];
21     int find(int x) {return x==f[x]?f[x]:f[x]=find(f[x]);}
22     struct Tree {int son[2],fa,w,rev;}t[maxn];
23     bool isrt(int x) {return s(fa(x),0)!=x&&s(fa(x),1)!=x;}
24     void pushup(int x) {t[x].w=t[s(x,0)].w+t[s(x,1)].w+1;}
25     void pushdown(int x) {
26         if(t[x].rev) {
27             swap(s(x,0),s(x,1));
28             t[s(x,0)].rev^=1;t[s(x,1)].rev^=1;
29             t[x].rev=0;
30         }
31     }
32     void push(int x) {
33         if(!isrt(x)) push(fa(x));
34         pushdown(x);
35     }
36     void rotate(int x) {
37         int y=fa(x),z=fa(y);
38         int l=s(y,1)==x,r=l^1;
39         if(!isrt(y)) s(z,s(z,1)==y)=x;
40         fa(x)=z;fa(y)=x;fa(s(x,r))=y;
41         s(y,l)=s(x,r);s(x,r)=y;
42         pushup(y);pushup(x);
43     }
44     void splay(int x) {
45         push(x);
46         while(!isrt(x)) {
47             int y=fa(x),z=fa(y);
48             if(!isrt(y)) {
49                 if(s(z,0)==y^s(y,0)==x) rotate(x);
50                 else rotate(y);
51             }
52             rotate(x);
53         }
54     }
55     void access(int x) {for(int pre=0;x;pre=x,x=fa(x)) {splay(x);s(x,1)=pre;pushup(x);}}
56     void makert(int x) {access(x);splay(x);t[x].rev^=1;}
57     int dis(int u,int v) {makert(u);access(v);splay(v);return t[v].w;}
58     void link(int u,int v) {
59         int fx=find(u),fy=find(v);
60         if(fx!=fy) {
61             makert(u);fa(u)=v;
62             int a=0,b,c;
63             if(dis(px[fx],py[fx])>a) a=dis(px[fx],py[fx]),b=px[fx],c=py[fx];
64             if(dis(px[fy],py[fy])>a) a=dis(px[fy],py[fy]),b=px[fy],c=py[fy];
65             if(dis(px[fx],py[fy])>a) a=dis(px[fx],py[fy]),b=px[fx],c=py[fy];
66             if(dis(px[fx],px[fy])>a) a=dis(px[fx],px[fy]),b=px[fx],c=px[fy];
67             if(dis(py[fx],px[fy])>a) a=dis(py[fx],px[fy]),b=py[fx],c=px[fy];
68             if(dis(py[fx],py[fy])>a) a=dis(py[fx],py[fy]),b=py[fx],c=py[fy];
69             f[fx]=fy;px[fy]=b;py[fy]=c;
70         }
71     }
72     int query(int u) {
73         int x=find(u);
74         return max(dis(px[x],u),dis(py[x],u));
75     }
76 }lct;
77 int main() {
78     type=read();
79     n=read(),q=read();
80     for(int i=1;i<=n;i++) lct.f[i]=lct.px[i]=lct.py[i]=i;
81     int lastans=0;
82     while(q--) {
83         int t=read();
84         if(t==1) {
85             int u=read()^(lastans*type),v=read()^(lastans*type);
86             lct.link(u,v);
87         }
88         else {
89             int u=read()^(lastans*type);
90             lastans=lct.query(u)-1;
91             printf("%lld\n",lastans);
92         }
93     }
94 }
View Code

 

posted @ 2018-12-27 07:48  wls001  阅读(157)  评论(0编辑  收藏  举报