Topic links
Test instructions
Given a tree, each side has black and white color, initially white, there are now three kinds of operations:
1 u v:u to v path (shortest) on the edges are taken to the opposite color
2 U v:u to v path the adjacent edges are taken to the opposite color (adjacent that is only one node on the path)
3 u V: query How many black edges are on the U-v path
Ideas:
Tree chain is divided into heavy chain and light chain, with two tree segments w,l to maintain. W maintains the rollover of edges between U and V on the heavy chain in the tree (operations on the [Pos[v],pos[u]] interval on the segment tree), and maintains the rollover of adjacent edges between U and V on the heavy chain in the tree. Then the final rollover condition of the edge of a certain point U with its Father node Fa[u] is: w (Pos[u], Pos[u]) (If the Edge is an edge on a heavy chain), W (Pos[u], pos[u]) ^l (Pos[fa[u]], and (if the edge is a light chain). For the 1 operation, simply maintain on the W is possible. For the 2 operation, in addition to the operation on the L, but also pay attention to the special treatment of the head and tail (because for the point in the heavy chain, not including the tail, only on the W query), that is, U of the heavy chain son son[u] and U's chain head p=belong[u] to flip once on the W, combined with the diagram may be There is also the operation of the line tree.
Other than that:
U may not have son[u], the default is virtual point 0, then in the line segment tree need to add a sentence: if (l = = r) return;
#include <bits/stdc++.h>const int N = 1e5 + 5;//segment Tree # define Lson L, Mid, O << 1#define rson mid + 1, R, O <& Lt 1 | 1struct seg_tree {int fp[n<<2], s[n<<2]; void Flip (int l, int r, int o) {S[o] = (r-l + 1)-s[o]; Fp[o] ^= 1; } void push_up (int o) {S[o] = s[o<<1] + s[o<<1|1]; } void Push_down (int l, int r, int o) {if (Fp[o]) {int mid = L + R >> 1; Flip (Lson); Flip (Rson); Fp[o] = 0; }} void Build (int l, int r, int o) {Fp[o] = S[o] = 0; if (L = = r) {return; } int mid = L + R >> 1; Build (Lson); Build (Rson); } void Updata (int ql, int qr, int l, int r, int o) {if (QL <= l && r <= qr) {Flip (L, R, O); return; } if (L = = r) return; //! Push_down (L, R, O); int mid = L + R >> 1; if (QL <= mid) Updata (QL, QR, Lson); if (QR > Mid) updata (QL, QR, Rson); PUSH_UP (o); } int query (int ql, int qr, int l, int r, int o) {if (QL <= l && r <= qr) {return s[o ]; } push_down (L, R, O); int mid = L + R >> 1, ret = 0; if (QL <= mid) ret + = query (QL, QR, Lson); if (QR > mid) ret + = query (QL, QR, Rson); PUSH_UP (o); return ret; }}w, l;std::vector<int> edge[n];int sz[n], dep[n], son[n], Fa[n];int pos[n], belong[n];int loc;int n;int query (int u , int v) {int p = belong[u], q = belong[v], ret = 0; while (P! = q) {if (Dep[p] < dep[q]) {Std::swap (P, q); Std::swap (U, v); } if (U! = p) {ret + = W.query (Pos[son[p]], pos[u], 1, N, 1); } ret + = (w.query (pos[p], pos[p], 1, N, 1) ^ l.query (Pos[fa[p]], pos[fa[p]], 1, N, 1); U = fa[p]; p = Belong[u]; } if (U = = v) return ret; if (Dep[u] < Dep[v]) {std::swap (U, v); } ret + = W.query (Pos[son[v], pos[u], 1, N, 1); return ret;} void Modify (int t, int u, int v) {int p = belong[u], q = belong[v]; while (P! = q) {if (Dep[p] < dep[q]) {Std::swap (P, q); Std::swap (U, v); } if (t = = 1) {w.updata (pos[p], pos[u], 1, N, 1); } else {l.updata (pos[p], pos[u], 1, N, 1); W.updata (Pos[son[u]], Pos[son[u]], 1, N, 1); W.updata (Pos[p], pos[p], 1, N, 1); } u = fa[p]; p = Belong[u]; } if (Dep[u] < Dep[v]) {std::swap (U, v); } if (t = = 1) {if (U = = v) return; W.updata (Pos[son[v]], pos[u], 1, N, 1); } else {l.updata (pos[v], pos[u], 1, N, 1); W.updata (Pos[son[u]], Pos[son[u]], 1, N, 1); W.updata (Pos[v], pos[v], 1, N, 1); }}//tree chain split void DFS2 (int u, int chain) {Pos[u] = ++loc; BElong[u] = chain; if (Son[u]) {DFS2 (Son[u], chain); } for (auto V:edge[u]) {if (v = = Fa[u] | | v = = Son[u]) continue; DFS2 (V, v); }}void DFS1 (int u, int pa) {Sz[u] = 1; Dep[u] = Dep[pa] + 1; Son[u] = 0; FA[U] = PA; for (auto V:edge[u]) {if (v = = PA) continue; DFS1 (V, u); Sz[u] + = Sz[v]; if (Sz[son[u]] < SZ[V]) son[u] = v; }}void prepare () {sz[0] = dep[0] = fa[0] = 0; DFS1 (1, 0); loc = 0; DFS2 (1, 1); W.build (1, N, 1); L.build (1, N, 1);} void Init_edge (int n) {for (int i=1; i<=n; ++i) {edge[i].clear (); }}int Main () {int T; scanf ("%d", &t); while (t--) {scanf ("%d", &n); Init_edge (n); for (int i=1; i<n; ++i) {int u, v; scanf ("%d%d", &u, &v); Edge[u].push_back (v); Edge[v].push_back (U); } prepare (); int q; scanf ("%d", &q); while (q--) {int T, u, v; scanf ("%d%d%d", &t, &u, &v); if (t = = 3) {printf ("%d\n", Query (U, v)); } else {modify (t, u, v); }}} return 0;}
Tree chain split + segment tree hdoj 4897 Little Devil I (small demon)