Problem address: http://acm.hdu.edu.cn/showproblem.php? PID = 1, 3966
[Preface]
A few days ago, the learning tree chain was split. We mainly make a template for the competition. However, basic questions cannot be found.
The line segment tree part of this question is not the simplest one. It uses other people's templates.
The last Wa has not been touched for several days.
But when I got up and looked at it this morning, I changed a place and it was over.
It seems that the most difficult task should be done in the morning.
[Idea]
To put it simply, the tree chain is split.
The Application of tree link partitioning is to dynamically modify the edge weight of a tree, and dynamically query the information on the path between each two nodes, including the greatest value, sum, and so on.
Tree chain partitioning divides a tree from top to bottom into individual chains. The advantage of this is that the tree can be segmented during update or query.
See http://blog.sina.com.cn/s/blog_7a1746820100wp67.html for details
There are a lot of online code and few are explained. In the above article, I think it is very detailed, and the examples are also in place.
After reading this information, I found that the line segment tree is used for updating or querying!
The application of a line segment tree includes the maximization, sum, and so on. It also includes segment update and query.
[Code]
Tree link splitting and line segment Tree Code are used by others, but in fact tree link splitting is not as difficult as imagined.
# Include <iostream> using namespace STD; const int maxn = 50010; struct edgenode {int value; int to; int next;} edge [maxn * 2]; int ECT; int ehead [maxn]; int eroot; int TCT; int Dep [maxn], W [maxn], Fa [maxn], top [maxn], son [maxn], siz [maxn]; void initedge (int n) // tree initialization {ect = 0; eroot = 1; int I; for (I = 0; I <= N; I ++) ehead [I] =-1;} void insertedge (int from, int to, int value) // Insert the edge of a tree {edge [ect]. to = to; edge [ect]. valu E = value; edge [ect]. next = ehead [from]; ehead [from] = ECT; ect ++;} void dfs1 (INT v) // The first layer searches {siz [v] = 1; son [v] = 0; int I; for (I = ehead [v]; I + 1! = 0; I = edge [I]. Next) {If (edge [I].! = Fa [v]) {Fa [edge [I]. to] = V; Dep [edge [I]. to] = Dep [v] + 1; dfs1 (edge [I]. to); If (siz [edge [I]. to]> siz [son [v]) Son [v] = edge [I]. to; siz [v] + = siz [edge [I]. to] ;}} void dfs2 (int v, int TP) // second-level search to obtain the position in the online segment tree of each node {TCT ++; W [v] = TCT; top [v] = TP; If (son [v]! = 0) dfs2 (son [v], top [v]); int I; for (I = ehead [v]; I + 1! = 0; I = edge [I]. Next) {If (edge [I].! = Son [v] & edge [I].! = Fa [v]) dfs2 (edge [I]. to, edge [I]. to) ;}} int enemy [maxn]; // The Line Segment tree section # define lson L, M, RT <1 # define rson m + 1, R, RT <1 | 1 # define ll intll add [maxn <2]; ll sum [maxn <2]; void pushup (int rt) {sum [RT] = sum [RT <1] + sum [RT <1 | 1];} void Pushdown (int rt, int m) {If (add [RT]) {Add [RT <1] + = add [RT]; add [RT <1 | 1] + = add [RT]; sum [RT <1] + = add [RT] * (m-(M> 1 )); sum [RT <1 | 1] + = add [RT] * (M> 1); add [RT] = 0 ;}} void buildsegment (int l, int R, int RT) // create a line segment tree, which can be initialized to 0 {memset (ADD, 0, sizeof (ADD); memset (sum, 0, sizeof (SUM);/* Add [RT] = 0; If (L = r) {sum [RT] = 0; return;} int M = (L + r)> 1; buildsegment (lson); buildsegment (rson); pushup (RT ); */} void updatesegment (int l, int R, int C, int L, int R, int RT) // line segment tree Interval Update {If (L <= L & R <= r) {Add [RT] + = C; sum [RT] + = (LL) C * (R-l + 1); return;} Pushdown (RT, R- L + 1); int M = (L + r)> 1; if (L <= m) updatesegment (L, R, C, lson ); if (M <r) updatesegment (L, R, C, rson); pushup (RT);} ll querysum (int l, int R, int L, int R, int RT) // sum of the Line Segment tree intervals. However, this is not the sum of the intervals for tree link generation. {If (L <= L & R <= r) {return sum [RT];} Pushdown (RT, R-l + 1); int M = (L + r)> 1; ll ret = 0; if (L <= m) RET + = querysum (L, R, lson); If (M <r) RET + = querysum (L, R, rson ); return ret;} void Init (int n) // all initialization {er OOT = (n + 1)/2; Fa [eroot] = TCT = Dep [eroot] = 0; memset (siz, 0, sizeof (siz )); dfs1 (eroot); dfs2 (eroot, eroot); buildsegment (1, TCT, 1); // create an empty line segment tree int I; for (I = 1; I <= N; I ++) // update the initial weight to the line segment tree {updatesegment (W [I], W [I], enemy [I], 1, TCT, 1) ;}} void Update (INT va, int VB, int c) // update of tree link partitioning {int F1 = top [VA], f2 = top [VB]; while (F1! = F2) {If (DEP [F1] <Dep [F2]) {swap (F1, F2); swap (va, VB);} updatesegment (W [F1], W [VA], C, 1, TCT, 1); VA = Fa [F1]; F1 = top [VA];} // If (Va = VB) return; // because this question is point-based, you need to update if (DEP [VA]> Dep [VB]) {swap (va, VB );} updatesegment (W [VA], W [VB], C, 1, TCT, 1);} int main () {int n, m, p; int I; int X, y, Z; char cmd [5]; while (scanf ("% d", & N, & M, & P )! = EOF) {for (I = 1; I <= N; I ++) scanf ("% d", & enemy [I]); initedge (N ); for (I = 1; I <n; I ++) {scanf ("% d", & X, & Y); insertedge (X, Y, 0 ); insertedge (Y, X, 0);} Init (n); for (I = 0; I <p; I ++) {scanf ("% s", CMD ); if (CMD [0] = 'I') {scanf ("% d", & X, & Y, & Z); Update (x, y, z);} else if (CMD [0] = 'D') {scanf ("% d", & X, & Y, & Z ); update (X, Y,-z);} else {scanf ("% d", & X); printf ("% d \ n", querysum (W [X], W [X], 1, TCT, 1) ;}} return 0 ;}