Tree link partitioning solves a series of tree problems, such as insertion and query on the tree.
Assume that you have a tree, and there is no weight between the two sides. There are some operations. What is the maximum weight between 1: X --- y? 2: change the weight between X --- y
Currently, there are many such operations. If you use a brute-force method directly, you must think of a good method. can we solve this problem by using the line segment tree, can you think of a way to number the edge on the tree and then change it to a range. Then we can operate on the online segment tree, and tree chain partitioning is such an algorithm.
Application Scope: Modify the path, obtain the extreme value, and sum the path on a tree. For such a tree, each vertex is connected to only one vertex from the bottom up, that is, there is a unique path between any two points.
Division of heavy chain Light Chains
Data structure:
Number of nodes in the siz [u] root subtree
Depth of Dep [u] U (root: 1)
Fa [u] U's father
Son [u] Son of U on the same heavy chain
The top node of the chain where top [u] U is located
W [u] indicates the position in the online segment tree between the U and the parent node.
The split tree has the following properties:
Property 1: If (v, u) is a light edge, siz [u] * 2 <siz [v];
Property 2: the number of light and heavy chains in the path from the root to a certain point is not greater than logn.
Obtain DEP, siz, fa, son from dfs1 for the first time.
For the second dfs2 V, if Son [v] exists (V is not a leaf node ). Top [son [v] = top [v]
In a line segment tree, the heavy edge of V should be behind the parent edge of V. W [son [v] = totw + 1. totw indicates the position of the last added edge in the online section.
In this case, dfs2 (son [v])
For each son of V, the top [u] = u, W [u] = totw + 1,
Here, the position in the line segment tree can be matched one by one because the number of lines is-1. Use the P Array
Of course, the number is not a simple random number. If we create a line segment tree and update the weight of an edge, it is the complexity of log2 (n, for search, we need to enumerate all the edges between X -- Y. For example, if we randomly number a vertex as the root node, the maximum length is the diameter of the tree, this value itself is relatively large, and the complexity of searching for any interval on the online segment tree is also log2 (N). In this way, the time complexity of searching once is higher than that of direct brute force, obviously, this is not the case.
We have to figure out a solution. Can we search for some edges between x and y? This is about the heavy and light edges of tree link partitioning,
Duplicate edge: the edge between the child node with the largest number of nodes in the subtree formed by a node X to the child node. It is defined that only one duplicate edge exists for other nodes except the leaf node.
The duplicate edge can be updated together.
Nature: the number of light and heavy edges on the path from the root to a certain point is not greater than logn.
Therefore, the search time complexity is equivalent to log2 (n)
In fact, tree link partitioning refers to hashing edges to the data structure on the Line Segment tree.
The implementation is very simple. We use two DFS to process the number information, the heavy side and the light side, and then some line segment Tree operations.
Template ": Taking spoj 375 as an Example
# Include <cstdio> # include <cstring> # include <vector> # include <algorithm> using namespace STD; # define del (a, B) memset (A, B, sizeof (A) const int n= 10005; int Dep [N], siz [N], Fa [N], Id [N], son [N], val [N], top [N]; // The parent node int num of the top heavy chain; vector <int> V [N]; struct tree {int X, Y, Val; void read () {scanf ("% d", & X, & Y, & Val) ;}; tree e [N]; void dfs1 (int u, int F, int d) {Dep [u] = D; siz [u] = 1; son [u] = 0; fa [u] = F; For (INT I = 0; I <V [u]. size (); I ++) {int FF = V [u] [I]; If (FF = f) continue; dfs1 (FF, U, D + 1 ); siz [u] + = siz [ff]; If (siz [son [u] <siz [ff]) Son [u] = ff ;}} void dfs2 (int u, int TP) {top [u] = TP; Id [u] = ++ num; If (son [u]) dfs2 (son [u], TP); For (INT I = 0; I <V [u]. size (); I ++) {int FF = V [u] [I]; If (FF = Fa [u] | FF = Son [u]) continue; dfs2 (FF, ff) ;}# define lson (x) (x <1) # define rson (X) (x <1) + 1) struct tree {int L, R, Val;}; TREE tree [4 * n]; void pushup (int x) {tree [X]. val = max (tree [lson (x)]. val, tree [rson (x)]. val);} void build (int l, int R, int v) {tree [v]. L = L; tree [v]. R = r; If (L = r) {tree [v]. val = Val [l]; return;} int mid = (L + r)> 1; build (L, mid, V * 2); Build (Mid + 1, r, V * 2 + 1); pushup (V);} void Update (int o, int V, int Val) // log (N) {If (tree [O]. L = tree [O]. r) {tree [O]. val = val; Return ;} Int mid = (tree [O]. L + tree [O]. r)/2; If (v <= mid) Update (O * 2, V, Val); else Update (O * 2 + 1, V, Val ); pushup (o);} int query (int x, int L, int R) {If (tree [X]. l> = L & tree [X]. r <= r) {return tree [X]. val;} int mid = (tree [X]. L + tree [X]. r)/2; int ans = 0; If (L <= mid) ans = max (ANS, query (lson (x), L, R )); if (r> mid) ans = max (ANS, query (rson (x), L, R); Return ans;} int yougth (int u, int V) {int TP1 = T OP [u], TP2 = top [v]; int ans = 0; while (TP1! = TP2) {// printf ("Yes \ n"); If (DEP [TP1] <Dep [TP2]) {swap (TP1, TP2); swap (u, v);} ans = max (query (1, Id [TP1], Id [u]), ANS); U = Fa [TP1]; TP1 = top [u];} If (u = V) return ans; If (DEP [u]> Dep [v]) Swap (u, v ); ans = max (query (1, Id [son [u], Id [v]), ANS); Return ans;} void clear (int n) {for (INT I = 1; I <= N; I ++) V [I]. clear () ;}int main () {// freopen ("input.txt", "r", stdin); int t; scanf ("% d", & T ); while (t --) {Int N; scanf ("% d", & N); For (INT I = 1; I <n; I ++) {e [I]. read (); V [E [I]. x]. push_back (E [I]. y); V [E [I]. y]. push_back (E [I]. x);} num = 0; dfs1 (, 1); dfs2 (); For (INT I = 1; I <n; I ++) {If (DEP [E [I]. x] <Dep [E [I]. y]) Swap (E [I]. x, E [I]. y); Val [ID [E [I]. x] = E [I]. val;} build (1, num, 1); char s [200]; while (~ Scanf ("% s", & S) & S [0]! = 'D') {int X, Y; scanf ("% d", & X, & Y); If (s [0] = 'q ') printf ("% d \ n", yougth (x, y); If (s [0] = 'C') Update (1, Id [E [X]. x], Y);} Clear (n);} return 0 ;}
Tree link splitting (Template)