Hdu_4010
Because cut and join are required for this question, link-cut-tree must be used for writing.
Both cut and join operations involve a basic operation, that is, converting a node into a root (makeroot). If you can write the makeroot operation successfully, cut and join are better done.
In fact, after the access (x) operation, if we want to use X as the root, we only need to "reverse" the parent-child relationship of the edge on this path, then, you just need to rotate X to the root, and then swap the position of the splay and the Left and Right sons of the Child tree, that is, marking the Rev (reverse.
In addition, pay attention to some details. For example, in some operations, if X is equal to Y, do you need to determine whether or not.
# Include <stdio. h> # Include < String . H># Define Maxd 300010 # Define Maxm 600010 # Define INF 0x7fffffff Int N, first [maxd], E, next [maxm], V [maxm], Q [maxd]; Struct Splay { Int PRE, ls, RS, key, Max, Rev, add; Bool Root; Void Update (); Void Pushdown ();Void Zig ( Int ); Void Zag ( Int ); Void Splay ( Int ); Void RENEW () {Root = True ; Pre = Ls = rs = 0 ; Rev = Add = 0 ;}} SP [maxd]; Int Max ( Int X, Int Y ){ Return X> Y? X: Y ;} Void Splay: Update () {max = Max (max (SP [ls]. Max, SP [RS]. max), key );} Void Makeadd ( Int Cur, Int Delta ){ If (Cur) SP [cur]. Add + = Delta, SP [cur]. Key + = delta, SP [cur]. MAX + = Delta ;} Void Swap ( Int & X, Int & Y ){ Int T; t = X, x = Y, y = T ;} Void Makerev ( Int Cur) {SP [cur]. Rev ^ =1 ; Swap (SP [cur]. ls, SP [cur]. RS );} Void Splay: Pushdown (){ If (ADD) makeadd (LS, add), makeadd (RS, add), add = 0 ; If (REV) makerev (LS), makerev (RS), Rev = 0 ;} Void Splay: Zig ( Int X ){ Int Y = RS, fa = Pre; RS = Sp [Y]. ls, SP [RS]. Pre = X; SP [Y]. ls = X, pre = Y; SP [Y]. Pre = Fa; If (Root) Root = False , SP [Y]. Root = True ; Else SP [fa]. RS = X? SP [fa]. rs = Y: SP [fa]. ls =Y; Update ();} Void Splay: zag ( Int X ){ Int Y = ls, fa = Pre; LS = Sp [Y]. RS, SP [ls]. Pre = X; SP [Y]. RS = X, pre = Y; SP [Y]. Pre = Fa; If (Root) Root = False , SP [Y]. Root = True ; Else SP [fa]. RS = X? SP [fa]. rs = Y: SP [fa]. ls = Y; Update ();} Void Splay: splay ( Int X ){ Int Y, Z; For (Pushdown ();! Root;) {Y = Pre; If (SP [Y]. Root) SP [Y]. Pushdown (), Pushdown (), SP [Y]. RS = X? SP [Y]. Zig (y): SP [Y]. Zag (y ); Else {Z = SP [Y]. Pre; SP [Z]. Pushdown (), SP [Y]. Pushdown (), Pushdown (); If (SP [Z]. rs = Y ){ If (SP [Y]. rs = X) SP [Z]. Zig (z), SP [Y]. Zig (y ); Else SP [Y]. Zag (Y), SP [Z]. Zig (z );} Else { If (SP [Y]. ls = X) SP [Z]. Zag (z), SP [Y]. Zag (y ); Else SP [Y]. Zig (Y), SP [Z]. Zag (z) ;}} Update ();} Void Access ( Int X ){ Int FX; For (FX = x, x = 0 ; FX! = 0 ; X = FX, FX = SP [X]. PRE) {SP [FX]. splay (FX); SP [Sp [FX]. RS]. Root = True ; SP [FX]. RS = X, SP [X]. Root = False ; SP [FX]. Update ();}} Void Makeroot ( Int X) {access (x); SP [X]. splay (x); makerev (x );} Void Prepare (){ Int I, j, X, rear = 0 ; SP [ 0 ]. Max =- INF; Q [rear ++] = 1 ; SP [ 1 ]. RENEW (), SP [ 1 ]. Max = Sp [ 1 ]. Key; For (I = 0 ; I <rear; I ++) {X = Q [I]; For (J = first [X]; J! =- 1 ; J = Next [J]) If (V [J]! = SP [X]. PRE) {SP [V [J]. RENEW (), SP [V [J]. Pre = X, SP [V [J]. max = SP [V [J]. Key; Q [rear ++] = V [J] ;}} Void Add ( Int X, Int Y) {v [E] = Y; next [E] = First [X], first [x] = e ++ ;} Void Init (){ Int I, X, Y; memset (first, - 1 , Sizeof (First); e = 0 ; For (I = 1 ; I <n; I ++) {Scanf ( " % D " , & X ,& Y); add (x, y), add (Y, x );} For (I = 1 ; I <= N; I ++ ) Scanf ( " % D " ,& SP [I]. Key); Prepare ();} Void Join ( Int X,Int Y ){ If (X = Y) {printf ( " -1 \ n " ); Return ;} Makeroot (x); makeroot (y ); If (SP [X]. Pre = 0 ) SP [Y]. Pre = X; Else Printf ( " -1 \ n " );} Void Cut ( Int X, Int Y) {makeroot (x); Access (y); SP [Y]. splay (y ); If (SP [X]. Pre = 0 ) Printf ( " -1 \ n " ); Else { Int T = SP [Y]. ls; SP [T]. Root = True , SP [T]. Pre = 0 , SP [Y]. ls = 0 ; SP [Y]. Update ();}} Void Change ( Int X, Int Y, Int Z ){ Int FY; makeroot (y); makeroot (X ); If (SP [Y]. Pre = 0 ) Printf ( " -1 \ n " ); Else {Access (X ); For (FY = Y, y = 0 ; FY! = 0 ; Y = fy, FY =SP [Y]. PRE) {SP [FY]. splay (FY ); If (SP [FY]. Pre = 0 ) {Makeadd (SP [FY]. RS, Z), makeadd (Y, Z); SP [FY]. Key + = Z;} SP [Sp [FY]. RS]. Root = True ; SP [FY]. RS = Y, SP [Y]. Root = False ; SP [FY]. Update ();}}} Void Query ( Int X,Int Y ){ Int FY; If (X = Y) {SP [X]. splay (x); printf ( " % D \ n " , SP [X]. Key ); Return ;} Makeroot (y); makeroot (X ); If (SP [Y]. Pre = 0 ) Printf ( " -1 \ n " ); Else {Access (X ); For (FY = Y, y = 0 ; FY! = 0 ; Y = fy, FY = SP [Y]. PRE) {SP [FY]. splay (FY ); If (SP [FY]. Pre = 0 ) Printf ( " % D \ n " , Max (SP [Sp [FY]. RS]. max, SP [Y]. max), SP [FY]. key); SP [Sp [FY]. RS]. root = True ; SP [FY]. RS = Y, SP [Y]. Root = False ; SP [FY]. Update ();}}} Void Solve (){ Int I, X, Y, Z, m, OP; scanf ( " % D " ,& M ); For (I = 0 ; I <m; I ++ ) {Scanf ( " % D " , & OP, & X ,& Y ); If (OP = 1 ) Join (x, y ); Else If (OP = 2 ) Cut (x, y ); Else If (OP = 3 ) {Scanf ( " % D " ,& Z); change (Y, Z, x );} Else Query (x, y );}} Int Main (){ While (Scanf (" % D " , & N) = 1 ) {Init (); solve (); printf ( " \ N " );} Return 0 ;}