1. 程式人生 > >[loj6038]「雅禮集訓 2017 Day5」遠行 lct+並查集

[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