CSU 1607: Do You Have The Template? (Tree link splitting), csu1607
1607: Do You Have The Template? Time Limit: 7 Sec Memory Limit: 128 MB
Submit: 112 Solved: 8
[Submit] [Status] [Web Board] Description
There is a tree with N vertices, each edges have a positive length.
And here comes 4 operations,
0 a B, means query the maximum length and the sum of length on the path between vertex a and vertex B.
1 a B, means change the-th edge's length to B.
2 a B 0 c, means change all edges 'length on the path between vertex a and vertex B to c.
2 a B 1 c, means add all edges 'length on the path between vertex a and vertex B by c.
Input
There're several cases.
The first line contains a positive integer N (2 <= N <= 10000), meaning there're N vertices, marked 1 to N. then N-1 lines follow with the I-th line describing the I-th edge. each line contains three integers a B c, meaning there is an edge between vertex a and vertex B with the length of c.
Then one integer M (M <= 10000), means there're M queries. And followed by M lines, each line will contain one operation described as above.
Output
For each 0 a B query, you should output the maximum length and the sum.
The data insure no number will be bigger than 2 ^ 31.
Sample Input
41 2 12 3 22 4 3100 1 30 1 40 3 41 2 30 1 32 4 3 0 20 1 42 4 3 1 20 1 30 1 4
Sample Output
2 33 43 53 42 34 54 5
A tree has n nodes and each edge has the right value. Now there are M operations:
0 a B indicates the maximum edge weight and the sum of edge trees in the output path from vertex a to vertex B.
1 a B indicates that the weight of edge a is changed to B
2 a B 0 c indicates that each edge right in the path from point a to point B is changed to c
2 a B 1 c indicates that each edge right in the path from point a to point B is added with c
Pitfall: In this CSU question, use vector to create a map and then use WA. The program code has a vulnerability. It uses root [k]. toc to determine whether to update the Left and Right subnodes of k in the line segment tree.
Solution: Use tree link to split. Use a line segment tree to maintain Edge Weight.
# Include <stdio. h> # include <string. h ># include <vector> const int N = 10015; using namespace std; int head [N], to [N <1], next1 [N <1], tot; int top [N]; // top [v] = u table point v, u in a chain, and u is the smallest point in the chain depth (that is, the top) int fath [N]; // records the parent node int deep [N]; // The depth of each point in the tree int num [N]; // number of nodes in each subtree int son [N]; // The selected duplicate edge node int p [N]; // The vertex int pos corresponding to each vertex online segment in the tree; void addEdge (const int & u, const int & v) {to [tot] = v, next1 [tot] = head [u], head [u] = tot + +;} Void addUndirEdge (const int & u, const int & v) {addEdge (u, v), addEdge (v, u);} void init (int n) {pos = 0; tot = 0; memset (son,-1, sizeof (son); memset (head,-1, sizeof (head ));} void dfs1 (int u, int pre, int d) {deep [u] = d; fath [u] = pre; num [u] = 1; for (int I = head [u]; I! =-1; I = next1 [I]) {int v = to [I]; if (v = pre) continue; dfs1 (v, u, d + 1 ); num [u] + = num [v]; if (son [u] =-1 | num [v]> num [son [u]) son [u] = v ;}} void getpos (int u, int root) {top [u] = root; p [u] = pos ++; if (son [u] =-1) return; getpos (son [u], root); for (int I = head [u]; I! =-1; I = next1 [I]) {int v = to [I]; if (son [u]! = V & v! = Fath [u]) getpos (v, v) ;}// line segment tree struct tree {int sum, maxv, toc, addc;} root [N * 4]; int val [N]; int MAX (int a, int B) {return a> B? A: B;} void build (int l, int r, int k) {int mid = (l + r)/2; root [k]. addc = 0; root [k]. toc = 0; if (l = r) {root [k]. sum = root [k]. maxv = val [l]; return;} build (l, mid, k <1); build (mid + 1, r, k <1 | 1 ); root [k]. sum = root [k <1]. sum + root [k <1 | 1]. sum; root [k]. maxv = MAX (root [k <1]. maxv, root [k <1 | 1]. maxv);} void upson (int k, int l, int r) {int mid = (l + r)/2; if (root [k]. toc) {root [k <1]. sum = (mid-l + 1) * root [k]. toc; root [k <1]. maxv = roo T [k]. toc; root [k <1]. toc = root [k]. toc; root [k <1]. addc = 0; root [k <1 | 1]. sum = (r-mid) * root [k]. toc; root [k <1 | 1]. maxv = root [k]. toc; root [k <1 | 1]. toc = root [k]. toc; root [k <1 | 1]. addc = 0; root [k]. toc = 0;} if (root [k]. addc) {root [k <1]. sum + = (mid-l + 1) * root [k]. addc; root [k <1]. maxv + = root [k]. addc; root [k <1]. addc + = root [k]. addc; root [k <1 | 1]. sum + = (r-mid) * root [k]. addc; root [k <1 | 1]. maxv + = root [k]. addc; root [k <1 | 1]. Addc + = root [k]. addc; root [k]. addc = 0 ;}} void updata1 (int l, int r, int k, const int L, const int R, int c) {if (L <= l & r <= R) {root [k]. sum = (r-l + 1) * c; root [k]. maxv = c; root [k]. toc = c; root [k]. addc = 0; return;} int mid = (l + r)/2; upson (k, l, r); if (L <= mid) updata1 (l, mid, k <1, L, R, c); if (mid <R) updata1 (mid + 1, r, k <1 | 1, L, R, c ); root [k]. sum = root [k <1]. sum + root [k <1 | 1]. sum; root [k]. maxv = MAX (root [k <1]. maxv, root [k <1 | 1]. Maxv);} void updata2 (int l, int r, int k, int L, int R, int c) {if (L <= l & r <= R) {root [k]. sum + = (r-l + 1) * c; root [k]. maxv + = c; root [k]. addc + = c; return;} int mid = (l + r)/2; upson (k, l, r); if (L <= mid) updata2 (l, mid, k <1, L, R, c); if (mid <R) updata2 (mid + 1, r, k <1 | 1, L, R, c); root [k]. sum = root [k <1]. sum + root [k <1 | 1]. sum; root [k]. maxv = MAX (root [k <1]. maxv, root [k <1 | 1]. maxv);} int sum, maxv; void query (int l, int r, int k, int L, int R) {if (L <= l & r <= R) {sum + = root [k]. sum; maxv = MAX (maxv, root [k]. maxv); return;} int mid = (l + r)/2; upson (k, l, r); if (L <= mid) query (l, mid, k <1, L, R); if (mid <R) query (mid + 1, r, k <1 | 1, L, R );} void swp (int & a, int & B) {int tt; tt = a; a = B; B = tt;} void Operat0 (int u, int v) {int f1 = top [u], f2 = top [v]; sum = 0; maxv = 0; while (f1! = F2) {if (deep [f1] <deep [f2]) {swp (f1, f2); swp (u, v);} query (1, pos, 1, p [f1], p [u]); u = fath [f1]; f1 = top [u];} if (u = v) return; if (deep [u]> deep [v]) swp (u, v); query (1, pos, 1, p [son [u], p [v]);} void Operat1 (int u, int v, int c) {int f1 = top [u], f2 = top [v]; while (f1! = F2) {if (deep [f1] <deep [f2]) {swp (f1, f2); swp (u, v);} updata1 (1, pos, 1, p [f1], p [u], c); u = fath [f1]; f1 = top [u];} if (u = v) return; if (deep [u]> deep [v]) swp (u, v); updata1 (1, pos, 1, p [son [u], p [v], c);} void Operat2 (int u, int v, int c) {int f1 = top [u], f2 = top [v]; while (f1! = F2) {if (deep [f1] <deep [f2]) {swp (f1, f2); swp (u, v);} updata2 (1, pos, 1, p [f1], p [u], c); u = fath [f1]; f1 = top [u];} if (u = v) return; if (deep [u]> deep [v]) swp (u, v); updata2 (1, pos, 1, p [son [u], p [v], c);} struct EDG {int u, v, c;} edg [N]; int main () {int n, q, op, a, B; while (scanf ("% d", & n )! = EOF) {init (n); for (int I = 1; I <n; I ++) {scanf ("% d ", & edg [I]. u, & edg [I]. v, & edg [I]. c); addUndirEdge (edg [I]. u, edg [I]. v);} dfs1 (1, 1); getpos (1, 1); pos = n; for (int I = 1; I <n; I ++) {if (deep [edg [I]. u]> deep [edg [I]. v]) edg [I]. v = edg [I]. u; val [p [edg [I]. v] = edg [I]. c;} build (1, pos, 1); scanf ("% d", & q); while (q --) {scanf ("% d ", & op, & a, & B); if (op = 0) {Operat0 (a, B); printf ("% d \ n", maxv, sum);} else if (op = 1) updata1 (1, pos, 1, p [edg [a]. v], p [edg [a]. v], B); else {int tt, c; scanf ("% d", & tt, & c); if (tt = 0) Operat1 (, b, c); else Operat2 (a, B, c );}}}} /*************************************** * *********************** Problem: 1607 User: aking2015 Language: C ++ Result: Accepted Time: 912 MS Memory: 2180 kb ************************************** **************************/