远行
Time Limit: 20 Sec Memory Limit: 256 MBDescription
Input
Output
Sample Input
0
5 10
1 4 5
2 3
2 5
2 1
1 5 3
1 1 4
2 3
2 5
1 5 2
2 1
Sample Output
0
1
0
3
2
3
HINT
Main idea
每次连上一条边,询问一个点和其能到达最远的点的距离。
Solution
由于每次要脸上一条边,我们显然使用LCT,然后一个点到达的最远的点必然是树的直径上的端点,我们合并两棵树维护直径的时候,暴力分几种情况讨论一下即可。
Code
1 #include<iostream>
2 #include<algorithm>
3 #include<cstdio>
4 #include<cstring>
5 #include<cstdlib>
6 #include<cmath>
7 #include<vector>
8 using namespace std;
9 typedef long long s64;
10
11 const int ONE = 300005;
12 const int MOD = 1e9+7;
13
14 int Type,n,Q;
15 int opt,x,y;
16 int fat[ONE];
17 int Ans;
18
19 int get()
20 {
21 int res=1,Q=1; char c;
22 while( (c=getchar())<48 || c>57)
23 if(c=='-')Q=-1;
24 if(Q) res=c-48;
25 while((c=getchar())>=48 && c<=57)
26 res=res*10+c-48;
27 return res*Q;
28 }
29
30 int Find(int x)
31 {
32 if(fat[x]==x) return x;
33 return fat[x]=Find(fat[x]);
34 }
35
36 namespace LCT
37 {
38 int lc[ONE],rc[ONE],fa[ONE];
39 int hasRev[ONE];
40 int L[ONE],R[ONE],dis[ONE],size[ONE];
41
42 void pre()
43 {
44 for(int i=1;i<=n;i++)
45 fat[i]=L[i]=R[i]=i,
46 size[i]=1;
47 }
48
49 void Update(int x)
50 {
51 size[x] = size[lc[x]] + size[rc[x]] + 1;
52 }
53
54 bool is_real(int x)
55 {
56 return (lc[fa[x]]==x || rc[fa[x]]==x);
57 }
58
59 void tag_rev(int x)
60 {
61 hasRev[x]^=1;
62 swap(lc[x],rc[x]);
63 }
64
65 void tag_down(int x)
66 {
67 if(hasRev[x])
68 {
69 tag_rev(lc[x]);
70 tag_rev(rc[x]);
71 hasRev[x]=0;
72 }
73 }
74
75 void Turn(int x)
76 {
77 int y=fa[x],z=fa[y];
78 int b= x==lc[y]?rc[x]:lc[x];
79
80 fa[y]=x; fa[x]=z;
81 if(b) fa[b]=y;
82
83 if(z)
84 {
85 if(y==lc[z]) lc[z]=x;
86 else if(y==rc[z]) rc[z]=x;
87 }
88
89 if(x==lc[y]) rc[x]=y,lc[y]=b;
90 else lc[x]=y,rc[y]=b;
91
92 Update(y); Update(x);
93 }
94
95 void Splay(int x)
96 {
97 static int anc[ONE];
98 int anc_num=0;
99 anc[++anc_num] = x;
100 for(int i=x; is_real(i); i=fa[i]) anc[++anc_num]=fa[i];
101 while(anc_num>0) tag_down(anc[anc_num--]);
102 while(is_real(x))
103 {
104 if(is_real(fa[x]))
105 {
106 if( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x]) ) Turn(fa[x]);
107 else Turn(x);
108 }
109 Turn(x);
110 }
111 }
112
113 void access(int x)
114 {
115 for(int p=x,q=0; p; q=p,p=fa[q])
116 {
117 Splay(p);
118 rc[p] = q;
119 Update(p);
120 }
121 }
122
123 void make_root(int x)
124 {
125 access(x); Splay(x); tag_rev(x);
126 }
127
128 int dist(int x,int y)
129 {
130 make_root(x); access(y); Splay(y); return size[y]-1;
131 }
132
133 void link(int x,int y)
134 {
135 int lx,rx,ly,ry;
136 int Fx=Find(x), Fy=Find(y);
137 fat[Fy] = Fx;
138 make_root(x); fa[x]=y;
139 lx = L[Fx]; rx = R[Fx]; ly = L[Fy]; ry = R[Fy];
140
141 if(dist(lx,rx) >= dis[Fx]) dis[Fx]=dist(lx,rx), L[Fx]=lx, R[Fx]=rx;
142 if(dist(ly,ry) >= dis[Fx]) dis[Fx]=dist(ly,ry), L[Fx]=ly, R[Fx]=ry;
143
144 if(dist(lx,ly) >= dis[Fx]) dis[Fx]=dist(lx,ly), L[Fx]=lx, R[Fx]=ly;
145 if(dist(lx,ry) >= dis[Fx]) dis[Fx]=dist(lx,ry), L[Fx]=lx, R[Fx]=ry;
146 if(dist(rx,ly) >= dis[Fx]) dis[Fx]=dist(rx,ly), L[Fx]=rx, R[Fx]=ly;
147 if(dist(rx,ry) >= dis[Fx]) dis[Fx]=dist(rx,ry), L[Fx]=rx, R[Fx]=ry;
148
149 }
150
151 void Query(int x)
152 {
153 int Fx=Find(x);
154 Ans = max( dist(L[Fx],x),dist(R[Fx],x) );
155 printf("%d\n",Ans);
156 }
157 }
158
159 int main()
160 {
161 Type=get();
162 n=get(); Q=get();
163 LCT::pre();
164 while(Q--)
165 {
166 opt = get();
167 if(opt == 1)
168 {
169 x=get(); y=get();
170 if(Type==1) x^=Ans, y^=Ans;
171 LCT::link(x,y);
172 }
173 else
174 {
175 x=get();
176 if(Type==1) x^=Ans;
177 LCT::Query(x);
178 }
179 }
180
181 }