1. Concept 1. Dynamic sequence statistics dynamic sequence statistics means that any sequence statistics in a dynamic unordered set can be determined within O (lgn) time. 2. the base array structure is a red-black tree. The fields of each tree node include: Key [X], color [X], left [X], right [x] 3. additional information size [x]: number of internal nodes (including X) of the subtree rooted in node X, that is, the size of the subtree. If nil is defined, the size [nil [T] is 0 size [x] = size [left [x] + size [right [x] + 14. maintenance of information (1) insert operation: the first stage, starting from the root, drops along the tree and inserts the new node into the child of an existing node, the maintenance method for this phase is to increase the size of each node in the path by 1, and the time is the second stage of O (lgn), that is, the node is rising along the tree, do some color modification and rotation to keep the color black, such as left-rotate (t, x). The maintenance method is size [y] <-size [X], size [x] <-size [left [x] + size [right [x] + 1. Since it is rotated twice at most, the time is O (1) (2) delete operation: the first stage is to operate the search tree. The maintenance method is to set the size of each node in the path to-1, and the time is from the second stage of O (lgn) to three more rotations, the maintenance method is the same as above. The time is O (1) 5. design a new OS-select (X, I): Find the I-small keyword in the sequence statistics tree T, and the time is O (lgn) OS-rank (t, x ): given a pointer to the node X in the sequence statistics tree T, return the position of X in the linear sequence obtained after the center order traversal of T. The time is O (lgn) II. Code 1. OS _tree.h
# Include <iostream> using namespace STD; # define black 0 # define Red 1 // structure of the node Structure of the sequence statistics tree struct node {/* fields of the red/black tree */INT key; bool color; node * P; node * left; node * right;/* Additional information */INT size; // number of internal nodes of the subtree rooted in node X, x-> key = x-> left-> key + X-> right-> key + 1/* constructor */node (node * init, int K ): left (init), right (init), P (init), key (K), color (black), size (1 ){}}; // ordered statistic tree structure class OS _tree {public: node * root; node * nil; // sensen/* constructor */OS _tree () {nil = new Node (null,-1); root = nil; nil-> size = 0 ;};/* perform operations related to dynamic sequence statistics */node * OS _select (node * X, int I); int OS _rank (node * X);/* operations related to the red/black tree */void left_rotate (node * X); // left-hand void right_rotate (node * X ); // right-hand void OS _insert_fixup (node * z); // insert and adjust void OS _insert (node * z); // insert void OS _delete_fixup (node * X ); // Delete and adjust node * OS _delete (node * z); // Delete void print (); // output void print (node * X ); // output node * OS _search (node * X, int K); // search for the K keyword in the X subtree Node * tree_successor (node * X); // find the successor node * tree_minimum (node * X); // find the vertex with the smallest keyword}; // left-hand, y = x-> right. The left-hand side is the pivot of the chain between x and y. // The involved nodes include X, Y, Y-> left, change node = {P, L, r} as follows: // X = {X-> P, X-> left, y} to {y, x-> left, Y-> left} // y = {X, Y-> left, Y-> right} is changed to {X-> P, X, y-> right} // y-> left = {Y, Y-> left, Y-> left-> right} is changed to {X, y-> left, Y-> left-> right} void OS _tree: left_rotate (node * X) {// make y = x-> rightnode * Y = x-> right; // follow the preceding steps to modify The pointer of the three nodes. Change the pointer sequence X-> right = Y-> left; If (Y-> left! = Nil) Y-> left-> P = x; y-> P = x-> P; If (X-> P = nil) // special case: X is the root node root = y; else if (x = x-> P-> left) x-> P-> left = y; else X-> P-> right = y; y-> left = x; X-> P = y; // maintenance of additional information y-> size = x-> size; x-> size = x-> left-> size + X-> right-> size + 1;} // right-hand, y = x-> left, left-hand rotation is based on the chain between x and y. // The rotation process is similar to void OS _tree: right_rotate (node * X) {node * Y = x-> left; x-> left = Y-> right; if (Y-> right! = Nil) Y-> right-> P = x; y-> P = x-> P; If (X-> P = nil) root = y; else if (x = x-> P-> right) x-> P-> right = y; else X-> P-> left = y; y-> right = x; X-> P = y; // maintenance of additional information y-> size = x-> size; x-> size = x-> left-> size + X-> right-> size + 1;} // adjust void OS _tree: OS _insert_fixup (node * z) {node * Y; // The only condition that needs to be adjusted. This is the violation of nature 2. If it does not violate nature 2, adjust the end while (Z-> P-> color = red) {// P [Z] is the left child, in three cases, if (Z-> P = z-> P-> left) {// set Y to the Z node y = z-> P-> righ T; // In the first case, Uncle y of Z is red if (Y-> color = red) {// Black P [Z] and y to solve the problem that both Z and P [Z] are red Z-> P-> color = black; y-> color = black; // place P [p [Z] in red to keep the property 5z-> P-> color = Red; // use P [p [Z] as the newly added node Z to repeat the while loop z = z-> P;} else {// The second case: z's uncle is black, and Z is the right child if (Z = z-> P-> right) {// to P [Z] left, in the third case, Z = z-> P; left_rotate (z);} // In the third case, the uncle of Z is black, and Z is the color of the left child // swap P [Z] and P [p [Z], and right-hand Z-> P-> color = black; z-> P-> color = Red; right_rotate (Z-> P) ;}// P [Z] is the right child There are three cases, similar to the above else if (Z-> P = z-> P-> right) {Y = z-> P-> left; If (Y-> color = red) {z-> P-> color = black; y-> color = black; Z-> P-> color = Red; Z = z-> P ;} else {If (Z = z-> P-> left) {z = z-> P; right_rotate (z);} Z-> P-> color = black; z-> P-> color = Red; left_rotate (Z-> P );}}} // set the root node to black root-> color = black;} // insert a node void OS _tree: OS _insert (node * z) {node * Y = nil, * x = root; // locate the position to be inserted, which is the same as that of the Binary Search Tree! = Nil) {X-> size ++; y = x; If (Z-> key <X-> key) x = x-> left; elsex = x-> right;} Z-> P = y; If (y = nil) root = z; else if (Z-> key <Y-> key) y-> left = z; Elsey-> right = z; Z-> left = nil; Z-> right = nil; // convert the newly inserted node into red Z-> color = Red; // start from the newly inserted node and adjust OS _insert_fixup (z) up;} // adjust the tree, X points to a red-black node. The adjustment process is to move the extra black along the tree void OS _tree: OS _delete_fixup (node * X) {node * W; // if this extra black is on a root node or a red node, the node will absorb the extra black and become a black node while (X! = Root & X-> color = black) {// If X is the left node of its parent node (which corresponds to the right node) if (x = x-> P-> left) {// Let W be the brother of X, depending on W, there are three cases: // before the delete operation is executed, X will certainly have no brothers. After the delete operation is executed, X will certainly have brothers W = x-> P-> right; // first case: W is the red if (W-> color = red) {// change the color of W and P [x] W-> color = black; x-> P-> color = Red; // perform a left-handed left_rotate (X-> P) on P [X ); // new brother w = x-> P-> right for w x; // converts it to one of the three situations} // Case 2: W is black, both children of W are black if (W-> left-> color = Black & W-> right-> color = black) {// remove the Black W and X. // W has only one black layer. The color turns red, and X has an extra black layer. After removing the color, the original color w-> color = Red is restored; // Add a black X = x-> P on P [X]; // The New X has an extra black color, transfer to for loop continue processing} // The third case, W is black, W-> left is red, w-> right is a black else {If (W-> right-> color = black) {// change the color of W and left [x] W-> left-> color = black; W-> color = Red; // perform a right-handed right_rotate (w) on W. // The new brother w whose W is X = x-> P-> right; // This is the fourth case} // The fourth case: W is black and W-> left is black, w-> right is red. // modify the color of W and P [x] W-> color = x-> P-> color; x-> P-> color = black; W-> right-> color = black; // P [x] performs a left-hand left_rotate (X-> P); // at this time, the adjustment has ended. set X to the root node to end the cycle x = root ;}} // If X is the left node of its parent node (which corresponds to the right node) else if (x = x-> P-> right) {// Let W be the brother of X. According to W, there are three cases for processing // before performing the delete operation, X is definitely not a brother, after the delete operation is executed, X must have a sibling W = x-> P-> left; // first case: W is a red if (W-> color = red) {// change the color of W and P [x] W-> color = black; X-> P-> color = Red; // perform a left-handed right_rotate (X-> P) on P [X]; // The new brother w whose W is X = x-> P-> left; // convert to one of the three situations} // The second case: W is black, both children of W are black. If (W-> right-> color = Black & W-> le FT-> color = black) {// remove the Black W and X. // w only has one black layer. The removed black layer turns red, and X has another black layer, remove and restore the original color w-> color = Red; // Add a black X = x-> P on P [x; // now there is an extra black on the new X, which is transferred to the for loop for further processing} // In the third case, W is black, W-> right is red, w-> left is a black else {If (W-> left-> color = black) {// change the color of W and right [x] W-> right-> color = black; W-> color = Red; // perform a right-hand left_rotate (w) on W. // The new brother w whose W is X = x-> P-> left; // This is the fourth case} // The fourth case: W is black, W-> right is black, w-> left is red. // modify the color of W and P [x] W-> color = x-> P-> color; X-> P-> C Olor = black; W-> left-> color = black; // perform a left-hand right_rotate (X-> P) operation on P [X]; // The adjustment has ended, set X as the root node to end the cycle x = root; }}// absorb the extra black X-> color = black;} // find the minimum node * OS _tree :: tree_minimum (node * X) {// if there is a node smaller than the current node while (X-> left! = Nil) x = x-> left; return X;} // search for the successor of the x node in the middle sequence. The successor is the smallest node * OS _tree greater than the key [x :: tree_successor (node * X) {// if there is a right child if (X-> right! = Nil) // return tree_minimum (X-> right), the minimum value in the right subtree. // if the right subtree of X is empty and X has a next y, then Y is the lowest ancestor node of X, and the left son of Y is also node * Y = x-> P; while (y! = NULL & X = Y-> right) {x = y; y = Y-> P;} return y ;} // recursively query the Binary Search Tree node * OS _tree: OS _search (node * X, int K) {// The leaf node is not found yet, or the current node is the searched node if (X-> key =-1 | K = x-> key) return X; // The searched node is located in the left subtree of the current node if (k <X-> key) return OS _search (X-> left, k ); // The searched node is located in the left subtree else return OS _search (X-> right, K) of the current node;} // delete node * OS _tree of the red/black tree :: OS _delete (node * z) {// locate the node and delete it. This part is the same as the delete node * X and * y of the Binary Search Tree; if (Z-> left = N Il | Z-> right = nil) y = z; else y = tree_successor (z); node * P = Y-> P; while (P! = Nil) {P-> size --; P = p-> P;} If (Y-> left! = Nil) x = Y-> left; else x = Y-> right; X-> P = Y-> P; If (Y-> P = nil) root = x; else if (y = Y-> P-> left) Y-> P-> left = x; Elsey-> P-> right = X; if (y! = Z) Z-> key = Y-> key; // If the deleted node is black, adjust if (Y-> color = black) OS _delete_fixup (x); Return y;} void OS _tree: Print (node * X) {If (X-> key =-1) return; print (X-> left); cout <X-> key <''<X-> color <Endl; print (X-> right );} void OS _tree: Print () {print (Root); cout <Endl;} // search for node * OS _tree, which is the largest node in the tree with X as the root node :: OS _select (node * X, int I) {// set the number of dots in the left subtree of X to R-1, int r = x-> left-> size + 1; // then, if (r = I) return X, the node with the largest R value in the X tree; // The element with the largest I value is in the X-> In left, else if (I <r) return OS _select (X-> left, I ); // elements larger than I are in X-> right elsereturn OS _select (X-> right, I-r );} // The position of X in the linear order obtained after sequential traversal in the computing tree t int OS _tree: OS _rank (node * X) {// set R to the rank int r = x-> left-> size + 1 of key [x] In the subtree with X as the root; node * Y = X; while (y! = Root) {// if Y is the right child of P [Y, all nodes in the left subtree of P [y] and P [y] are prior to xif (y = Y-> P-> right) R = R + Y-> P-> left-> size + 1; y = Y-> P;} return r ;}
2. Main. cpp
# Include <iostream> # include "OS _tree.h" using namespace STD; int main () {char ch; int X; // generate an Ordered Statistics tree OS _tree * t = new OS _tree; while (1) {CIN> CH; Switch (CH) {// insert an element case 'I': {CIN> X; node * z = new node (t-> nil, x); t-> OS _insert (z); break;} // delete an element case 'D ': {CIN> X; node * z = T-> OS _search (t-> root, x); If (Z = NULL) cout <"not exist" <Endl; elset-> OS _delete (z); break;} // calculate the case 's': {CIN> X; node * z = T-> OS _select (t-> root, x); If (Z = NULL) cout <"not exist" <Endl; elsecout <z-> key <Endl; break;} // calculate the position of X in case 'r': {CIN> X; node * z = T-> OS _search (t-> root, x); If (Z = NULL) cout <"not exist" <Endl; elsecout <t-> OS _rank (z) <Endl; break;} case 'p': T-> Print (); break; default: break ;}} return 0 ;}
Iii. Exercises
14.1-3
// 14.1-3 Non-recursive search for node * OS _tree: OS _select_iterative (node * X, int I) in the tree with X as the root node) {// start searching for the root node while (X! = NULL) {int r = x-> left-> size + 1; // If if (r = I) return X is found; // if the position is higher, if (I <r) x = x-> left; // if the position is higher, else {x = x-> right; I = I-r ;}}}
14.1-4
// 14.1-4 recursively calculate the position of X in the linear sequence obtained after sequential traversal in tree t int OS _tree: OS _rank_recursion (node * root, node * X) {If (X-> key = root-> key) return root-> left-> size + 1; if (X-> key> root-> key) // number of nodes in the left subtree + root node + x rank return root in the right node-> left-> size + 1 + OS _rank_recursion (root-> right, X ); // rank return OS _rank_recursion (root-> left, x) in the left subtree );}
14.1-5
// 14.1-5 determine X in the linear order of the tree the I-th successor node * OS _tree: Next (node * X, int I) {// is the current node if (I = 0) return X; // In the right subtree of X if (X-> right! = Nil & X-> right-> size> = I) return OS _select (X-> right, I ); // or else in the right subtree of an ancestor of X {// find the ancestor of an "right subtree" and "X is not in its right subtree" while (X-> P! = NULL & X = x-> P-> right) x = x-> P; // The root node is found, stop searching if (X-> P = NULL) {cout <"error: not exist" <Endl; exit (0 );} // recursive search next (x, I-1) for this ancestor );}}
15.1-6
When rank [x] is added, if it is inserted into the left subtree of the x node, rank [x] = rank [x] + 1; otherwise, it will not be deleted, if the deleted node is in the left subtree of X, rank [x] = rank [x]-1; otherwise, if left-handed is executed on X, with y = x-> right, rank [x] remains unchanged. If rank [y] = rank [y] + rank [x] is right-handed, with y = x-> left, rank [y] remains unchanged, rank [x] = rank [x] + rank [y]
14.1-7
See introduction to algorithms-14.1-7
This section describes how to use a tree array or a merge sort to find reverse order pairs. Here we use order statistics.
The Reverse Order Number of a number S [I] in the array indicates the number of numbers before S [I] But greater than s [I.
According to the OS _rank () of the sequence statistic, after each inserted element x, we can obtain the number of numbers larger than X in the existing element.
14.1-8 [transfer]
The angle is used to determine whether two strings are intersecting, so that they can be completed in O (N * logn.
For the two strings P1P2 and q1q2 (clockwise), the vector formed by the center and Endpoint has an angle.
If a (P1) <A (Q1) <A (P2) <A (Q2) or a (Q1) <A (P1) <A (Q2) <A (P2). In this way, the angle interval "crossover" means that the two strings have crossover.
The problem of counting the logarithm of the Cross string from an angle is essentially the same as that of the reverse order pair.
This can be seen as a typical application of "sequence statistics tree.
The basis for determining whether two strings are intersecting is whether there is a "cross" phenomenon in the "angle" range mentioned above.
(Note that when one interval contains another interval, it cannot be counted as "Cross ")
First, N strings have a total of 2n endpoints. Each endpoint corresponds to an angle in [* PI) for the center.
We sort the 2N angles according to the angle (actually the clockwise direction). This step requires O (N * logn)
For each string, its two endpoints can be regarded as "event points": scanning the circle counterclockwise from the 0 angle, the first point of a string can be regarded as the "starting point" of the string, and the second point is regarded as the "ending point" of the string ".
Then, we use a "sequence statistics Tree" to assist in processing (Initialization is empty of course ).
Traverse the 2N endpoints in a descending order of angle: if the endpoint is the "start point" of a string X {insert string X into the sequence statistics tree (using the "Start Point" angle of X as the key );} if the endpoint is the "endpoint" of a string X {count the "Start Point" angle of the number of strings in this tree to be greater than the "Start Point" angle of X, this is the number of substrings that intersect with X. // For the sequence statistics tree, as long as O (logn) can delete the string X from the sequence statistics tree; // this step also requires O (logn )}