Uva_11994
This topic has fewer barriers to thinking, because it is actually the basic operation of link-cut-tree, and a more complex link-cut-tree question --Hdu_4010.
When maintaining the number of colors above the path, because there are only 30 color categories, you can use 30 binary bits of an integer to store the color categories.
# Include <stdio. h> # Include < String . H> # Define Maxd 50010 Int N, m; Struct Splay { Int PRE, ls, RS, Col, Set , To, size; Bool Root; Void Pushdown (); Void Update (); Void Zig ( Int X ); Void Zag ( Int X ); Void Splay ( Int X ); Void Init () {Root = True ; Size = To = pre = ls = rs = Col = Set = 0 ;}} SP [maxd]; inline Void Same ( Int X, Int C ){ If (X) SP [X]. To = Sp [X]. Col = C, SP [X]. Set = 1 <C;} inline Void Splay: Pushdown (){ If (To) {same (LS, to), same (RS, to); = 0 ;} Inline Void Splay: Update (){ Set = Sp [ls]. Set | SP [RS]. Set | 1 < Col; Size = Sp [ls]. Size + SP [RS]. Size + 1 ;} 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 Cut ( Int X) {access (x), SP [X]. splay (x); SP [Sp [X]. ls]. Root = True , SP [Sp [X]. ls]. Pre =0 , SP [X]. ls = 0 ; SP [X]. Update ();} Void Join ( Int X, Int Y, Int C) {access (Y), SP [Y]. splay (y); SP [X]. splay (X ); If (SP [Y]. Pre! = 0 ) Return ; Cut (x); SP [X]. Pre = Y, SP [X]. Col = C; SP [X]. Update ();} Void Init (){ Int I, X; For (I = 1 ; I <= N; I ++ ) {Scanf ( " % D " ,& X); SP [I]. INIT (), SP [I]. Pre = X ;} For (I = 1 ; I <= N; I ++) {Scanf ( " % D " ,& X); SP [I]. Col = X, SP [I]. Set = 1 <X, SP [I]. size = 1 ;} SP [ 0 ]. INIT ();} Void Paint ( Int X, Int Y,Int C ){ Int FX; Access (Y), SP [Y]. splay (y ); For (FX = x, x = 0 ; FX! = 0 ; X = FX, FX = SP [X]. PRE) {SP [FX]. splay (FX ); If (SP [FX]. Pre = 0 ){ If (SP [Y]. Pre! = 0 | FX =Y) Same (SP [FX]. RS, c), same (x, c);} SP [Sp [FX]. RS]. Root = True , SP [FX]. rs = x, SP [X]. Root = False ; SP [FX]. Update ();}} Void Count ( Int X, Int Y ){ Int FX; Access (Y), SP [Y]. splay (y ); For (FX = x, x = 0 ; FX! = 0 ; X = FX, FX = SP [X]. PRE) {SP [FX]. splay (FX ); If (SP [FX]. Pre = 0 ){ If (SP [Y]. Pre = 0 & FX! = Y) printf ( " 0 0 \ n " ); Else { Int CNT =0 , T = Sp [Sp [FX]. RS]. Set | SP [X]. Set ; For ( Int I = 1 ; I <= 30 ; I ++) If (T & 1 <I) ++ CNT; printf ( " % D \ n " , SP [Sp [FX]. RS]. Size + SP [X]. Size, CNT) ;}sp [Sp [FX]. RS]. Root = True , SP [FX]. rs = x, SP [X]. Root = False ; SP [FX]. Update ();}} Void Solve (){ Int I, op, X, Y, C; For (I = 0 ; I <m; I ++ ) {Scanf ( " % D " ,& OP ); If (OP = 1 ) {Scanf ( " % D " , & X, & Y ,& C ); If (X = y) Continue ; Join (X, Y, c );} Else If (OP =2 ) {Scanf ( " % D " , & X, & Y ,& C ); If (X = y) Continue ; Paint (X, Y, c );} Else {Scanf ( " % D " , & X ,&Y ); If (X = y) printf ( " 0 0 \ n " ); Else Count (x, y );}}} Int Main (){ While (Scanf ( " % D " , & N, & M) = 2 ) {Init (); solve ();} Return 0 ;}