Title Link: xjoi-noi2015-13-c
Problem analysis
Solve this problem with a magical line-segment tree combined with the time complexity of O (NLOGN).
A line tree is established for each point on the tree, and key is the time (i.e., the first several operations) and the dynamic opening point.
The nodes of the segment tree maintain two values, one is the number of 1 operations during this time period, and the other is the black node weights and values that have changed over the period.
When dealing with all operations, each line tree is only a point on the tree, so each node of the line tree is maintained by this point as a 1 operation number and the time of the point of the Black node weights and (this point x from Black to white on-X, from white to black on +x).
After all the operations have been processed, we perform a DFS and merge the segment tree from the bottom up.
Currently DFS (x), recursively finishes each subtrees tree of x, then enumerates each subtrees tree of x, and sequentially merges their segment tree into the tree of segments on X.
Now that the segment tree of the j-1 subtrees Tree of X has been merged into the X segment tree, the segment tree of the J subtrees Tree is now merged into the x segment tree.
For the A in the J subtree and the black dots in the X-point or pre-j-1 subtrees tree, their LCA is X-point, so they contribute to the weight of X.
Similarly, the black dots in the J subtree and a in the X-point or the j-1 subtrees tree, their LCA is also an X-point, and they also calculate their contribution to the X's weight value.
A black-point weight modification can have an effect on the 1 operation of the time key that is larger than its value.
When merging, the two lines of the merged tree are (x, y), then the answer is to add son[x][0] of the black point weights Modified * Son[y][1] The number of 1 operations.
Similarly, the answer should also add son[y][0] The black point weights Modified * Son[x][1] The number of 1 operations.
Then recursively merge (Son[x][0], son[y][0]), merge (Son[x][1], son[y][1]), and continue to calculate the inner answer of both sides of the subtree.
Note also that the answer to this calculation does not include the weight of a point in itself as a black dot, so the weight of the case should be added separately.
Code
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath > #include <algorithm>using namespace std;typedef long long ll;inline void Read (int &num) {char c = GetChar (); b Ool Neg = False;while (c < ' 0 ' | | c > ' 9 ') {if (c = = '-') Neg = True;c = GetChar ();} Num = C-' 0 '; c = GetChar (); while (c >= ' 0 ' && C <= ' 9 ') {num = num * + C-' 0 '; c = GetChar ();} if (Neg) Num *=-1;} const int MAXN = 200000 + 5, Maxnode = 7200000 + 5;int N, M, Index;int A[MAXN], ROOT[MAXN], son[maxnode][2], T[maxnode]; LL Cnt; LL ANS[MAXN], sum[maxnode];struct Edge{int v; Edge *next;} E[MAXN * 2], *p = E, *point[maxn];inline void Addedge (int x, int y) {++p; P-v = y; P-Next = point[x]; POINT[X] = P;} inline void Update (int x) {t[x] = T[son[x][0]] + t[son[x][1]; SUM[X] = sum[son[x][0]] + sum[son[x][1]];} void Add (int &x, int s, int t, int Pos, int Ds, int Dt) {if (x = = 0) x = ++index;if (s = = t) {sum[x] + = (LL) Ds; T[X] + = Dt;retuRN;} int m = (s + t) >> 1;if (pos <= m) Add (Son[x][0], S, M, Pos, Ds, Dt); else Add (son[x][1], M + 1, T, Pos, Ds, Dt); U Pdate (x);} int Merge (int x, int y, int s, int t) {if (!x) return y;if (!y) return x;if (s = = t) {t[x] + = T[y]; SUM[X] + = Sum[y];return x;} Cnt + = (LL) t[son[x][1]] [sum[son[y][0]]; Cnt + = (LL) t[son[y][1]] * sum[son[x][0]];int m = (s + T) >> 1; Son[x][0] = Merge (son[x][0], son[y][0], S, m); SON[X][1] = Merge (son[x][1], son[y][1], M + 1, t); Update (x); return x;} void Solve (int x, int Fa) {for (Edge *j = point[x]; j; j = J-Next) {if (J-v = = Fa) continue; Solve (J-V, x);} for (Edge *j = point[x]; j; j = J-Next) {if (J-v = = Fa) continue; Cnt = 0; ROOT[X] = Merge (root[x], root[j-v], 0, M); ANS[X] + = Cnt;}} int main () {scanf ("%d%d", &n, &m), for (int i = 1; I <= n; ++i) {Read (a[i]); if (a[i]! = 1) A[i] = 0;} int A, b;for (int i = 1; i < n; ++i) {Read (a); Read (b); Addedge (A, b); Addedge (b, a);} for (int i = 1; I <= n; ++i) Add (Root[i], 0, M, 0, A[i] * i, 0); int f, x;for (int i = 1; I <= m; ++i) {Read (f); Read (x), if (f = = 1) {ADD (root[x], 0, M, I, 0, 1), if (A[x]) ans[x] + = (LL) x;} ELSE{A[X] ^= 1;if (a[x]) Add (Root[x], 0, M, I, x, 0); else Add (Root[x], 0, M, I,-X, 0);}} Solve (1, 0); for (int i = 1; I <= n; ++i) printf ("%lld\n", Ans[i]); return 0;}
[Xjoi NOI2015 simulation question 13] C white black Tree "segment tree Merge"