题目大意
有
n
个点和
Data Constraint
n≤300000,Q≤500000
题解
比较裸的启发式,用并查集维护直径,合并的时候启发式一下即可。
时间复杂度: O(nlog2n+Qlogn)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 600000 + 10
const int MAXN = 19 ;
struct Query {
int op , u , v ;
} P[N] ;
struct Note {
int u , v , len ;
Note ( int X = 0 , int Y = 0 , int Z = 0 ) { u = X , v = Y , len = Z ; }
} d[N] ;
int f[N][MAXN] ;
int Node[2*N] , Next[2*N] , Head[N] , tot ;
int Dist[N] , Deep[N] , fa[N] , Size[N] ;
int type , n , Q ;
int Read() {
int ret = 0 ;
char ch = getchar() ;
while ( ch < '0' || ch > '9' ) ch = getchar() ;
while ( ch >= '0' && ch <= '9' ) {
ret = ret * 10 + ch - '0' ;
ch = getchar() ;
}
return ret ;
}
void link( int u , int v ) {
Node[++tot] = v ;
Next[tot] = Head[u] ;
Head[u] = tot ;
}
void Pre( int x ) {
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == f[x][0] ) continue ;
f[Node[p]][0] = x ;
Dist[Node[p]] = Dist[x] + 1 ;
Deep[Node[p]] = Deep[x] + 1 ;
Pre( Node[p] ) ;
}
}
int Get( int x ) { return fa[x] == x ? x : fa[x] = Get(fa[x]) ; }
int LCA( int x , int y ) {
if ( Deep[x] < Deep[y] ) swap( x , y ) ;
for (int i = MAXN - 1 ; i >= 0 ; i -- ) {
if ( Deep[f[x][i]] >= Deep[y] ) x = f[x][i] ;
}
if ( x == y ) return x ;
for (int i = MAXN - 1 ; i >= 0 ; i -- ) {
if ( f[x][i] != f[y][i] ) x = f[x][i] , y = f[y][i] ;
}
return f[x][0] ;
}
int CalcDist( int u , int v ) { return Dist[u] + Dist[v] - 2 * Dist[LCA(u,v)] ; }
Note Merge( Note a , Note b ) {
Note ret ;
if ( a.len > b.len ) ret = a ;
else ret = b ;
int dist = CalcDist( a.u , b.u ) ;
if ( dist > ret.len ) ret = Note( a.u , b.u , dist ) ;
dist = CalcDist( a.u , b.v ) ;
if ( dist > ret.len ) ret = Note( a.u , b.v , dist ) ;
dist = CalcDist( a.v , b.u ) ;
if ( dist > ret.len ) ret = Note( a.v , b.u , dist ) ;
dist = CalcDist( a.v , b.v ) ;
if ( dist > ret.len ) ret = Note( a.v , b.v , dist ) ;
return ret ;
}
void Solve0() {
for (int i = 1 ; i <= Q ; i ++ ) {
P[i].op = Read() ;
if ( P[i].op == 1 ) {
P[i].u = Read() , P[i].v = Read() ;
link( P[i].u , P[i].v ) ;
link( P[i].v , P[i].u ) ;
} else P[i].u = Read() ;
}
for (int i = 1 ; i <= n ; i ++ ) {
if ( !f[i][0] ) Deep[i] = 1 , Pre( i ) ;
}
for (int j = 1 ; j < MAXN ; j ++ ) {
for (int i = 1 ; i <= n ; i ++ ) f[i][j] = f[f[i][j-1]][j-1] ;
}
for (int i = 1 ; i <= n ; i ++ ) fa[i] = i , d[i] = Note( i , i , 0 ) ;
for (int i = 1 ; i <= Q ; i ++ ) {
if ( P[i].op == 1 ) {
int fx = Get( P[i].u ) ;
int fy = Get( P[i].v ) ;
if ( Deep[fx] < Deep[fy] ) swap( fx , fy ) ;
fa[fx] = fy ;
d[fy] = Merge( d[fx] , d[fy] ) ;
} else {
int fx = Get( P[i].u ) ;
printf( "%d\n" , max( CalcDist( P[i].u , d[fx].u ) , CalcDist( P[i].u , d[fx].v ) ) ) ;
}
}
}
void DFS( int x ) {
for (int i = 1 ; i < MAXN ; i ++ ) f[x][i] = f[f[x][i-1]][i-1] ;
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == f[x][0] ) continue ;
f[Node[p]][0] = x ;
Deep[Node[p]] = Deep[x] + 1 ;
Dist[Node[p]] = Dist[x] + 1 ;
DFS( Node[p] ) ;
}
}
void Solve1() {
int lastans = 0 ;
for (int i = 1 ; i <= n ; i ++ ) fa[i] = i , Size[i] = Deep[i] = 1 , d[i] = Note( i , i , 0 ) ;
for (int i = 1 ; i <= Q ; i ++ ) {
int op = Read() ;
if ( op == 1 ) {
int u = Read() , v = Read() ;
if ( type ) u ^= lastans , v ^= lastans ;
int fx = Get(u) ;
int fy = Get(v) ;
if ( Size[fx] > Size[fy] ) {
swap( fx , fy ) ;
swap( u , v ) ;
}
link( u , v ) , link( v , u ) ;
fa[fx] = fy ;
Size[fy] += Size[fx] ;
Deep[u] = Deep[v] + 1 ;
Dist[u] = Dist[v] + 1 ;
f[u][0] = v ;
DFS( u ) ;
d[fy] = Merge( d[fy] , d[fx] ) ;
} else {
int u = Read() ;
if ( type ) u ^= lastans ;
int fx = Get(u) ;
lastans = max( CalcDist( u , d[fx].u ) , CalcDist( u , d[fx].v ) ) ;
printf( "%d\n" , lastans ) ;
}
}
}
int main() {
freopen( "hike.in" , "r" , stdin ) ;
freopen( "hike.out" , "w" , stdout ) ;
scanf( "%d%d%d" , &type , &n , &Q ) ;
if ( type == 0 ) Solve0() ;
else Solve1() ;
return 0 ;
}
以上.