Given a tree with edge weights at n (n <100001) nodes, perform the following Q (q <100001) operations:
1. Change the right of an edge of the tree;
2. Calculate the distance between the given vertex and a certain vertex. The latter is the node numbered 1. If operation 2 is executed for the first time, otherwise it is the given point for the last operation 2.
Analysis: If operation 1 is not performed, that is, the edge weight is not changed, it is a common problem to convert the value from LCA to rmq. If the edge weight is changed, does it mean that all the pre-processed data is useless? Otherwise, changing the weight of an edge will have a fixed impact on those edges. That is to say, if the Euler sequence is fixed, the weight of an edge will be changed, the DIS [] value of the entire subtree (distance from the root node) is changed, while in the Euler's sequence, the entire subtree is continuous ,, you only need to record the start and end positions of each node in the Euler's sequence by the way, which is a range of the Euler's sequence...
You can use a tree array to maintain a dis1 [I], that is, the difference between it and the original dis [I] after the change ..
View code
# Include <iostream> # Include <Algorithm> # Include < String . H> # Include <Math. h># Include <Stdio. h> Using Namespace STD; Const Int N = 100000 + 10 ; Struct Edge { Int V, NEX, W;} e [n * 2 ]; Struct Edge { Int U, V; Int W;} e [N]; Int Head [N], size, N; Int F [ 2 * N], B [ 2 * N], pos_s [N], pos_e [N], DIS [N], Bn; Int Tree [ 2 * N], DP [N * 2 ] [ 20 ]; Bool Vis [N]; Void Init () {memset (Head, - 1 , Sizeof (Head); memset (VIS, False , Sizeof (VIS); Size = 0 ;} Void Insert ( Int U,Int V, Int W) {e [size]. v = V; E [size]. W = W; E [size]. NEX = Head [u]; head [u] = Size ++ ;} // Dis [] records the distance from each node to the root node // F [] corresponds to the Euler's sequence, and B [] is the depth of each vertex corresponding to the Euler's sequence (this is obtained through the estimation of LCA) // Pos_s [] and pos_e [] respectively record the start and end positions of nodes in the Euler's sequence. Void DFS ( Int Cur, Int Deep, Int Len) {vis [cur] = True ; DIS [cur] = Len; F [bn] = Cur; B [bn] = Deep; pos_s [cur] = Bn ++ ; For ( Int I = head [cur]; I! =- 1 ; I =E [I]. NEX ){ Int V = E [I]. V; If (! Vis [v]) {DFS (v, deep + 1 , Len + E [I]. W); F [bn] = Cur; B [bn] = Deep; bn ++ ;}} Pos_e [cur] = BN- 1 ;} Void Init_rmq () {memset (DP, 0 , Sizeof (DP )); For ( Int I = 1 ; I <= Bn; ++ I) DP [I] [ 0 ] = I; For ( Int J = 1 ; J <= Log (( Double ) (BN +1 )/Log ( 2.0 ); ++ J ){ Int Limit = Bn + 1 -( 1 < J ); For ( Int I = 1 ; I <= limit; ++ I ){ Int X = DP [I] [J- 1 ]; Int Y = DP [I + ( 1 <(J- 1 )] [J- 1 ]; DP [I] [J] = B [x] <B [y]? X: Y ;}}} Int Rmq ( Int A, Int B ){ If (A> B) Swap (A, B ); Int K = ( Int ) (Log (( Double ) (B-A + 1 )/Log ( 2.0 )); Int X = DP [a] [k]; Int Y = DP [B + 1 -( 1 < K)] [k]; Return B [x] <B [y]? X: Y ;} Int Lowbit ( Int X ){ Return X &(- X );} Void Modify ( Int X, Int Add ){ While (X < 2 * N) {tree [x] + = Add; x + = Lowbit (x );}} Int Get_val ( Int X)// Single Point { Int Ret = 0 ; While (X> 0 ) {RET + = Tree [X]; x -= Lowbit (x );} Return RET ;} Int Main (){ Int Q, S; Int A, C; Int OP; While (Scanf ( " % D " , & N, & Q, & S) = 3 ) {Init (); For ( Int I = 1 ; I <n; ++ I) {scanf ( " % D " , & E [I]. U, & E [I]. V ,& E [I]. w); insert (E [I]. u, E [I]. v, E [I]. w); insert (E [I]. v, E [I]. u, E [I]. w);} bn = 1 ; DFS ( 1 , 0 , 0 ); -- Bn; init_rmq (); memset (tree, 0 , Sizeof (Tree )); While (Q -- ) {Scanf ( " % D " ,& OP ); If (OP = 0 ) {Scanf ( " % D " ,& A ); Int T = rmq (pos_s [s], pos_s [a]); // Returns the subscript of the closest common ancestor in the Euler's sequence. Int Ans = get_val (t) + dis [f [T]; // Get_val (t) only obtains the change value of the distance between the point marked as T in the Euler's sequence and the original distance. Ans = get_val (pos_s [s]) + dis [s]- 2 * Ans; ans + = Get_val (pos_s [a]) + Dis [a]; printf ( " % D \ n " , ANS); s =A ;} Else {Scanf ( " % D " , & ,& C ); Int W = c-e [A]. W, U; // Changed weight E [A]. W = C; If (DIS [E [A]. u] <dis [E [A]. V]) // Determine the node subtree that should be changed U = E [A]. V; Else U = E [A]. U; Int L = pos_s [u], r = Pos_e [u]; // Cout <L <''<r <Endl; Modify (R + 1 ,- W); Modify (L, W ); // The two operations change the range [L, R], which corresponds to the range of the Euler's sequence. }}} Return 0 ;}