Title Link: BZOJ-3626
Problem analysis
Considering this equivalence problem, if we assign a point x to the root of each point to the weight of 1, the remaining points of the weight of 0, then the Depth from the LCA (x, y) is from the Y to the root of the path on the right and the point.
This method can be superimposed, which is a very useful point. If we put [L, R] Each point to the root of all points on the path of the weight of +1, and then find the path from C to root of the right and, that is, [L, R] a bit with C of the LCA Depth and.
Not only to meet the additive, but also to meet the reduction, which is better!
Then we can make a difference to each inquiry [L, R], using query (r)-query (L-1) as the answer. Thus there is an off-line algorithm: N points in turn, to the root of the path of the point weight of +1, and if the point is a query l-1 or R, use the query C to find the path to Root and, in the answer.
done!
Forget the% Mod when you write the code is really weak ...
Code
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath > #include <algorithm> #include <queue> #include <vector>using namespace Std;const int maxn = 50000 + 5 , Mod = 201314;int N, m, Index;int FATHER[MAXN], DEPTH[MAXN], SIZE[MAXN], SON[MAXN], TOP[MAXN], Pos[maxn];int T[MaxN * 4], D[MAXN * 4], LEN[MAXN * 4], ANS[MAXN], q[maxn];vector<int> BA[MAXN], ea[maxn];struct Edge {int v; Edge *next;} E[MAXN], *p = E, *point[maxn];inline void Addedge (int x, int y) {++p; P-v = y; P-Next = point[x]; POINT[X] = P;} int dfs_1 (int x, int Dep) {depth[x] = dep; SIZE[X] = 1;int sonsize, maxsonsize; Sonsize = Maxsonsize = 1;for (Edge *j = point[x]; j; j = J-Next) {sonsize = Dfs_1 (J-V, DEP + 1); if (Sonsize &G T maxsonsize) {maxsonsize = sonsize; SON[X] = J-V;} SIZE[X] + = sonsize;} return size[x];} void dfs_2 (int x) {if (x = = Son[father[x]]) top[x] = Top[father[x]];else top[x] = x; POS[X] = ++index;if (son[x]! = 0) dfs_2 (son[x]), for (Edge *j = point[x]; j; j = J-Next) if (J-V! = son[x]) dfs_2 (J-v);} void Build_tree (int x, int s, int t) {len[x] = t-S + 1;d[x] = t[x] = 0;if (s = = t) return;int m = (s + t) >> 1; Build_tree (x << 1, S, m); Build_tree (x << 1 | 1, M + 1, t);} inline void Update (int x) {T[x] = t[x << 1] + t[x << 1 | 1]; T[X]%= Mod;} inline void Paint (int x, int Num) {t[x] + = Num * Len[x]; T[X]%= mod;d[x] + + num;d[x]%= Mod;} inline void pushdown (int x) {if (d[x] = = 0) return; Paint (x << 1, d[x]); Paint (x << 1 | 1, d[x]);D [x] = 0;} void Add (int x, int s, int t, int l, int r) {if (L <= s && r >= t) {Paint (x, 1); return;} Pushdown (x); int m = (s + t) >> 1;if (L <= m) Add (x << 1, S, M, L, R); if (r >= m + 1) Add (x << 1 | 1, M + 1, T, L, R); Update (x);} void Eadd (int x) {int fx;fx = Top[x];while (FX! = 1) {ADD (1, 1, N, Pos[fx], pos[x]); x = Father[fx];fx = Top[x];} ADD (1, 1, N, Pos[1], pos[x]);} int Get (int x, int s, int t, int l, int r) {if (L <= s && r >= T) return t[x];int ret = 0; Pushdown (x); int m = (s + t) >> 1;if (L <= m) ret + = Get (x << 1, S, M, L, R), if (R >= m + 1) ret + = Get (x << 1 | 1, M + 1, T, L, R); return ret% Mod;} int eget (int x) {int ret = 0, Fx;fx = top[x];while (FX! = 1) {ret + = Get (1, 1, N, Pos[fx], pos[x]); ret%= mod;x = father[f X];FX = Top[x];} RET + = Get (1, 1, N, Pos[1], pos[x]); return ret% Mod;} int main () {scanf ("%d%d", &n, &m); int A, B, c;for (int i = 2; I <= n; ++i) {scanf ("%d", &a); ++a; Father[i] = A; Addedge (A, i);} Dfs_1 (1, 1); Index = 0;dfs_2 (1); Build_tree (1, 1, n); for (int i = 1; I <= m; ++i) {scanf ("%d%d%d", &a, &b, &c); ++a; ++b; ++c; Q[i] = C;ba[a-1].push_back (i); Ea[b].push_back (i);} for (int i = 1; I <= n; ++i) {Eadd (i), for (int j = 0; J < ba[i].size (); ++j) Ans[ba[i][j]]-= Eget (Q[ba[i][j]]); for (int j = 0; J < ea[i].size (); ++j) ANS[EA[I][J]] + = Eget (Q[ea[i][j]);} for (int i =1; I <= m; ++i) printf ("%d\n", (Ans[i] + MoD)% mod); return 0;}
[Bzoj 3626] [LNOI2014] LCA "tree chain split + offline + differential query"