Portal: "HDU" 4918 Query on the subtree
Topic Analysis:
First, simplify the problem.
1. Ask for the number of points that do not exceed D at a time to the point U. Easy, O (NLOGN) point division can be done at once.
2. Perform the operation several times 1. At this time not every time O (NLOGN), too slow. We consider that for Point division, the center of gravity of the tree has LOGN layer, the first layer is the center of gravity of the whole tree, the second layer is the center of gravity of the first center of gravity, and so on, each time at least divided into two size of the sub-tree, so there is a LOGN layer. And, for a point, he belongs to the Logn tree at most, that is, at most, it belongs to Logn center of gravity. So we can preprocess the center of gravity of each point and the distance to the center of gravity, with each center of gravity of the array, each point in the distance to the center of gravity inserted into the tree array, and then each query to u distance not more than D of the number of points to be prefixed and obtained by the tree array.
Assuming a center of gravity x to u distance is dis, then statistics to the center of gravity x distance does not exceed the number of points d-dis, this process we call "borrowing force", its own limited ability, so need to rely on the influence of X. Because if this center of gravity is being borrowed by you, then the center of gravity must also be borrowed, because the points that are counted by the two center of gravity X and y of the adjacent force are duplicated, so we need to go heavy. If we go heavy, we'll open a tree-like array of V to X for each node, and the meaning of this tree array is: When the center of Gravity X's subtree V is at Y, the distance from each point to X in the subtree V is the tree array created by the subscript. Because the center of gravity X is the part of the center of Gravity y, the center of gravity X includes a portion of the center of gravity y must include, so the statistical time minus V on the tree array x is not more than the number of D-dis points. Access to all of the center of gravity you belong to, each borrowing force, at the same time to the weight, you can get the distance u not more than the number of points. Because the center of gravity is up to logn layers, each tree-like array has a maximum of n points, logn the complexity of the statistics, so each query complexity O (LOGN*LOGN).
We open up to 2 tree arrays per node, and the size of all tree arrays in each layer does not add up to N, so the tree array occupies an O (2NlogN) space.
3. The original problem: each point has the right value, altogether two kinds of operation: (1) asks to the U distance does not exceed D's all points the weight value and is how much; (2) Change the weight of a point to D.
This is just a little expansion on top of the base. When preprocessing is inserted into the tree array is the weight of the point, the query is still the statistical prefix and. When modifying the point weights, it is the same as the query, where you modify the weights of U in the tree array of x at the position of the U-distance center of gravity x distance D, and you modify the value of the same position in the tree array of V to X of the subtree V of the center of gravity X. The complexity is as O (LOGN*LOGN) as the query.
Total complexity of the algorithm: O (NLOGN*LOGN).
--------------------------------Split Line---------------------------------
This problem has been solved successfully.
Here's how I feel about extra:
Assuming that one of the center of Gravity X's center of gravity is Y, we think X is the parent of Y and Y is the child of X subtrees.
Under this hypothesis, all the center of gravity is a tree, the distance from each center of gravity to the root center of gravity (the center of gravity of the whole subtrees tree) is not more than Logn, and the path between the two centers of gravity will not exceed 2logN.
We can figure this tree as the "center of gravity Tree" ~
It is in the center of gravity tree any point to the root node of the path length does not exceed the nature of LOGN, the efficiency of the algorithm has been guaranteed ~
I believe this tree will have more good properties to be discovered. (for example, change a tree array to another data structure, such as a balance tree, etc.)
The code is as follows:
#include <vector> #include <cstdio> #include <cstring> #include <iostream> #include < algorithm>using namespace std; #define REP (I, A, b) for (int i = (a); I < (b); + i) #define for (I, a , b) for (int i = (a); I <= (b); + + i) #define REV (I, A, b) for (int i = (a); I >= (b);---I) #de Fine CLR (A, X) memset (A, x, sizeof a) const int MAXN = 100005; Const int maxe = 200005; Const int maxnode = 4000005 ; const int INF = 0x3f3f3f3f; struct Node {int root, subroot, dis, n; Node () {}node (int root, int subroot, int dis, int n): root (Root), Subroot (subroot), dis (dis), n (N) {}}; struct Edge {int V, n; Edge () {}edge (int v, int n): V (v), N (n) {}}, struct Tree {int n; vector < int > T; void init (int size ) {t.clear (); n = size; For (i, 0, N) t.push_back (0);} void Add (int x, int v) {for (int i = x; i <= n; i + = i & i) t[i] + = V;} int sum (int x, int ans =0) {if (x > N) x = n; for (int i = x; i > 0; I-= i &-i) ans + = t[i]; return ans;} ; Tree T[MAXN << 1]; Edge E[maxe]; Node N[maxnode]; int H[MAXN], cnte; int NODE[MAXN], cntn; int Q[MAXN], head, tail; int VAL[MAXN]; int VIS[MAXN], time int DEP[MAXN]; int SIZ[MAXN]; int PRE[MAXN]; int IDX[MAXN]; int cur; int n, m; int tot_size; void clear () {cur = 0; + +) time; cntn = Cnte = 0; CLR (H,-1); CLR (node,-1);} void Addedge (int u, int v) {E[cnte] = Edge (V, H[u]); H[u] = Cnte + +;} void AddNode (int u, int root, int subroot, int dis) {N[CNTN] = Node (root, Subroot, dis, node[u]); Node[u] = cn TN + +;} int get_root (int s) {head = tail = 0; Q[tail + +] = s;p re[s] = 0; while (head! = tail) {int u = q[head + +]; for (int i = h[u]; ~i; i = e[i].n) {int v = e[ I].V; if (v = = Pre[u] | | vis[v] = = time) continue;p re[v] = u; Q[tail + +] = V;}} tot_size = tail; int root = s, root_cnt = INF; while (tail) {int u = q[--tail]; siz[u] = 1; intCNT = 0; for (int i = h[u]; ~i; i = e[i].n) {int v = e[i].v; if (v = = Pre[u] | | vis[v] = = time) continue; Siz[u] + = SIZ[V]; if (Siz[v] > cnt) cnt = siz[v];} CNT = max (CNT, tot_size-siz[u]), if (CNT < root_cnt) {root = u; root_cnt = cnt;}} return root;} void Calc (int s, int root, int subroot) {head = tail = 0; Q[tail + +] = s;p re[s] = 0;d Ep[s] = 2;//dep[root] = 1 while (head! = tail) {int u = q[head + +]; T[root].add (Dep[u], val[u]); T[subroot].add (Dep[u], val[u]); AddNode (U, Root, Subroot, Dep[u]); for (int i = h[u]; ~i; i = e[i].n) {int V = E[I].V, if (v = = Pre[u] | | vis[v] = time) Continue;p re[v] = u;d ep[v] = Dep[u] + 1; Q[tail + +] = V;}}} void divide (int u) {int root = get_root (u); vis[root] = time; Idx[root] = + + cur; T[cur].init (tot_size); T[cur].add (1, val[root]); AddNode (Root, Idx[root], 0, 1); for (int i = h[root]; ~i; i = e[i].n) {int v = e[i ].V; if (vis[v] = = time) continue; t[++ Cur].init (Siz[v]+ 1); Calc (v, idx[root], cur);} for (int i = h[root]; ~i; i = E[I].N) if (VIS[E[I].V]! = time) divide (E[I].V);} void Solve () {clear (); Char op[5]; int u, V, D; For (i, 1, N) scanf ("%d", &val[i]), Rep (i, 1, n) {scanf ("%d%d", &u, &v), Addedge (U, v); Addedge (V, u);} Divide (1);//for (i, 1, cur) printf ("%d\n", T[i].sum (T[I].N)), while (M--) {scanf ("%s%d%d", OP, & u, &d); if (op[0] = = '? ') {int ans = 0; for (int i = node[u]; ~i; i = N[I].N) {int root = n[i].root, subroot = n[i].subroot, dis = N[i].dis- 1; ans + = t[root].sum (D-dis + 1); if (subroot) ans-= t[subroot].sum (D-dis + 1);} printf ("%d\n", ans);} else {for (int i = node[u]; ~i; i = N[I].N) {int root = n[i].root, subroot = n[i].subroot, dis = N[i].dis; T[root].add (DIS, d-val[u]); if (subroot) t[subroot].add (DIS, d-val[u]);} Val[u] = D;}}} int main () {CLR (VIS, 0); Time = 0; while (~scanf ("%d%d", &n, &m)) solve (); return 0;}
"HDU" 4918 Query on the subtree point Division + Tree Array