Problem
三种操作
1 x
把点x到根节点的路径上所有的点染上一种没有用过的新颜色。2 x y
求x到y的路径的权值。3 x
在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
显然挺板子的\(LCT\)啊 求个\(LCA\)套个线段树写一写。。
这里求\(LCA\)用了树剖?鬼知道为什么我用了树剖。。
// Isaunoya
#include
using namespace std ;
using LL = long long ;
using uint = unsigned int ;
#define int long long
#define fir first
#define sec second
#define pb push_back
#define mp(x , y) make_pair(x , y)
template < typename T > inline void read(T & x) { x = 0 ; int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
x *= f ;
}
template < typename T > inline void print(T x) {
if(! x) { putchar('0') ; return ; }
static int st[105] ;
if(x < 0) putchar('-') , x = -x ;
int tp = 0 ;
while(x) st[++ tp] = x % 10 , x /= 10 ;
while(tp) putchar(st[tp --] + '0') ;
}
template < typename T > inline void print(T x , char c) { print(x) ; putchar(c) ; }
template < typename T , typename ...Args > inline void read(T & x , Args & ...args) { read(x) ; read(args...) ; }
template < typename T > inline void sort( vector < T > & v) { sort(v.begin() , v.end()) ; return ; }
template < typename T > inline void unique( vector < T > & v) { sort(v) ; v.erase(unique(v.begin() , v.end()) , v.end()) ; }
template < typename T > inline void cmax(T & x , T y) { if(x < y) x = y ; return ; }
template < typename T > inline void cmin(T & x , T y) { if(x > y) x = y ; return ; }
const int Mod = LLONG_MAX ;
inline int QP(int x , int y) { int ans = 1 ;
for( ; y ; y >>= 1 , x = (x * x) % Mod)
if(y & 1) ans = (ans * x) % Mod ;
return ans ;
}
template < typename T > inline T gcd(T x , T y) { if(y == 0) return x ; return gcd(y , x % y) ; }
template < typename T > inline T lcm(T x , T y) { return x * y / gcd(x , y) ; }
template < typename T > inline void mul(T & x , T y) { x = 1LL * x * y ; if(x >= Mod) x %= Mod ; }
template < typename T > inline void add(T & x , T y) { if((x += y) >= Mod) x -= Mod ; }
template < typename T > inline void sub(T & x , T y) { if((x -= y) < 0) x += Mod ; }
int n , m ;
const int N = 1e5 + 5 ;
int d[N] , rev[N] ; int tot = 0 ;
int L[N << 2] , R[N << 2] ;
int tag[N << 2] ; int mx[N << 2] ;
inline void pushdown(int x) { if(! tag[x]) return ;
tag[x << 1] += tag[x] ; tag[x << 1 | 1] += tag[x] ;
mx[x << 1] += tag[x] ; mx[x << 1 | 1] += tag[x] ; tag[x] = 0 ;
}
inline void build(int l , int r , int rt) { if(l == r) { mx[rt] = d[rev[l]] ; return ; } int mid = l + r >> 1 ;
build(l , mid , rt << 1) ; build(mid + 1 , r , rt << 1 | 1) ; mx[rt] = max(mx[rt << 1] , mx[rt << 1 | 1]) ;
}
inline void update(int a , int b , int l , int r , int rt , int val) {
if(a <= l && r <= b) { tag[rt] += val ; mx[rt] += val ; return ; }
pushdown(rt) ; int mid = l + r >> 1 ;
if(a <= mid) update(a , b , l , mid , rt << 1 , val) ;
if(b > mid) update(a , b , mid + 1 , r , rt << 1 | 1 , val) ;
mx[rt] = max(mx[rt << 1] , mx[rt << 1 | 1]) ;
}
inline int query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return mx[rt] ; pushdown(rt) ;
int mid = l + r >> 1 ; int ans = 0 ;
if(a <= mid) cmax(ans , query(a , b , l , mid , rt << 1)) ;
if(b > mid) cmax(ans , query(a , b , mid + 1 , r , rt << 1 | 1)) ;
return ans ;
}
class LCT {
public : int rev[N] ; int fa[N] ; int ch[N][2] ;
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
inline bool isroot(int x) { return ls(fa[x]) != x && rs(fa[x]) != x ; }
inline bool getr(int x) { return rs(fa[x]) == x ; }
inline void pushr(int x) { if(! rev[x]) return ; swap(ls(x) , rs(x)) ; rev[ls(x)] ^= 1 ; rev[rs(x)] ^= 1 ; rev[x] ^= 1 ; }
inline void rotate(int x) { int y = fa[x] , z = fa[y] ; int k = getr(x) ;
if(! isroot(y)) ch[z][getr(y)] = x ; fa[x] = z ; ch[y][k] = ch[x][k ^ 1] ; fa[ch[x][k ^ 1]] = y ; ch[x][k ^ 1] = y ; fa[y] = x ;
}
inline void pushall(int x) { if(! isroot(x)) pushall(fa[x]) ; pushr(x) ;}
inline void splay(int x) { pushall(x) ; while(! isroot(x)) { int y = fa[x] ; if(! isroot(y)) rotate(getr(x) ^ getr(y) ? x : y) ; rotate(x) ; } }
inline int findroot(int x) {
while(ls(x)) x = ls(x) ; return x ;
}
inline void access(int x) { int son = 0 ;
for( int tp = 0 ; x ; tp = x , x = fa[tp]) { splay(x) ;
if(rs(x)) son = findroot(rs(x)) , update(L[son] , R[son] , 1 , n , 1 , 1) ;
if(rs(x) = tp) { son = findroot(tp) ; update(L[son] , R[son] , 1 , n , 1 , - 1) ; }
rs(x) = tp ;
}
}
} lct ;
struct node { int v , nxt ; } e[N << 1] ;
int head[N] , cnt = 0 ;
inline void add(int u , int v) { e[++ cnt].v = v ; e[cnt].nxt = head[u] ; head[u] = cnt ; }
int fa[N] ; int size[N] ; int son[N] ;
inline void Dfs(int u) { size[u] = 1 ; L[u] = ++ tot ; rev[tot] = u ;
for(register int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ; if(v == fa[u]) continue ;
fa[v] = lct.fa[v] = u ; d[v] = d[u] + 1 ; Dfs(v) ; size[u] += size[v] ;
if(size[v] > size[son[u]]) son[u] = v ;
} R[u] = tot ;
}
int top[N] ;
inline void Dfs2(int u , int tp) { top[u] = tp ;
if(! son[u]) return ; Dfs2(son[u] , tp) ;
for(register int i = head[u] ; i ; i = e[i].nxt) { int v = e[i].v ;
if(v == fa[u] || v == son[u]) continue ; Dfs2(v , v) ;
}
}
inline int lca(int x , int y) { int fx = top[x] , fy = top[y] ;
while(fx ^ fy) { if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ; x = fa[fx] , fx = top[x] ; }
if(d[x] > d[y]) swap(x , y) ;
return x ;
}
signed main() { read(n , m) ;
for(register int i = 1 ; i <= n - 1 ; i ++) { int u , v ; read(u , v) ; add(u , v) ; add(v , u) ;}
d[1] = 1 ; Dfs(1) , Dfs2(1 , 1) ; build(1 , n , 1) ;
for(register int i = 1 ; i <= m ; i ++) { int opt , x , y ; read(opt) ;
if(opt == 1) { read(x) ; lct.access(x) ; }
if(opt == 2) { read(x , y) ; int Lca = lca(x , y) ;
int ans = query(L[x] , L[x] , 1 , n , 1) ; int ans2 = query(L[y] , L[y] , 1 , n , 1) ; int ans3 = query(L[Lca] , L[Lca] , 1 , n , 1) ;
print(ans + ans2 - 2 * ans3 + 1 , '\n') ;
}
if(opt == 3) { read(x) ; int ans = query(L[x] , R[x] , 1 , n , 1) ; print(ans , '\n') ; }
}
return 0 ;
}