At first glance, I think this question is only offline. We can find all F (1, I, Z). The answer is equivalent to F (1, R, Z)-f (1, l-1, Z ). However, there is no specific method, but the depth of the LCA and there is a very clever way. Each time a vertex is added, the vertex weight from this vertex to the root path is + 1, in this way, we can calculate the LCA depth of a certain point and all previous points, and calculate the weights and values of the points on the path of the point to the root. In this way, we can use the tree link to quickly modify and obtain the answer, which solves the problem.
Code:
#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#include <queue>#define N 51000#define yu 201314using namespace std;struct sss{ int place, askp; int num, nump;}ask[N*2];struct ss{ int num, push;}t[N*4];int n, m, nowplace = 0;int p[N], v[N], next[N], bnum = 0;int ans[N][2] = {0};int fa[N], deep[N], siz[N], son[N], w[N], top[N];bool cmp(sss x, sss y) { return x.place < y.place; }void addbian(int x, int y){ bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y;}void build_tree(int now, int l, int r){ t[now].num = 0; t[now].push = 0; if (l == r) return; int mid = (l+r)/2; build_tree(now*2, l, mid); build_tree(now*2+1, mid+1, r);}void dfs_1(int now, int fat, int de){ int k = p[now]; fa[now] = fat; deep[now] = de; int maxsonnum = 0; siz[now] = 1; son[now] = 0; while (k) { if (v[k] != fat) { dfs_1(v[k], now, de+1); siz[now] += siz[v[k]]; if (siz[v[k]] > maxsonnum) { maxsonnum = siz[v[k]]; son[now] = v[k]; } } k = next[k]; } return;}void dfs_2(int now, int fat, int nowtop){ int k = p[now]; top[now] = nowtop; w[now] = ++nowplace; if (son[now]) dfs_2(son[now], now, nowtop); while (k) { if (v[k] != son[now] && v[k] != fat) dfs_2(v[k], now, v[k]); k = next[k]; } return;}void downdate(int now, int l, int r){ if (!t[now].push) return; int mid = (l+r)/2; t[now*2].push += t[now].push; t[now*2+1].push += t[now].push; t[now*2].num += (mid-l+1) * t[now].push; t[now*2+1].num += (r-mid) * t[now].push; if (t[now*2].num > yu) t[now*2].num %= yu; if (t[now*2+1].num > yu) t[now*2+1].num %= yu; t[now].push = 0; return;}void tadd(int now, int l, int r, int al, int ar){ if (al <= l && r <= ar) { t[now].num += r-l+1; if (t[now].num > yu) t[now].num %= yu; t[now].push ++; return; } int mid = (l+r)/2; downdate(now, l, r); if (al <= mid) tadd(now*2, l, mid, al, ar); if (ar > mid) tadd(now*2+1, mid+1, r, al, ar); t[now].num = t[now*2].num + t[now*2+1].num; if (t[now].num > yu) t[now].num %= yu;}int task(int now, int l, int r, int al, int ar){ if (al <= l && r <= ar) return t[now].num; int mid = (l+r)/2, zans = 0; downdate(now, l, r); if (al <= mid) zans = task(now*2, l, mid, al, ar); if (ar > mid) zans += task(now*2+1, mid+1, r, al, ar); if (zans > yu) zans %= yu; return zans;}int askk(int u, int v){ int f1 = top[u], f2 = top[v]; if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); } if (f1 == f2) { if (u == v) return task(1, 1, n, w[u], w[u]); return task(1, 1, n, min(w[u], w[v]), max(w[u], w[v])); } int zans = task(1, 1, n, w[f1], w[u]); zans += askk(fa[f1], v); if (zans > yu) zans %= yu; return zans;}void add(int u, int v){ int f1 = top[u], f2 = top[v]; if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); } if (f1 == f2) { if (u == v) tadd(1, 1, n, w[u], w[u]); else tadd(1, 1, n, min(w[u], w[v]), max(w[u], w[v])); return; } tadd(1, 1, n, w[f1], w[u]); add(fa[f1], v);}int main(){ scanf("%d%d", &n, &m); build_tree(1, 1, n); for (int i = 1; i < n; ++i) { int x; scanf("%d", &x); addbian(x+1, i+1); } dfs_1(1, 0, 1); dfs_2(1, 0, 1); for (int i = 1; i <= m; ++i) { int x, y, z; scanf("%d%d%d", &x, &y, &z); x++; y++; z++; ask[i*2-1].place = x-1; ask[i*2-1].askp = z; ask[i*2-1].num = i; ask[i*2-1].nump = 0; ask[i*2].place = y; ask[i*2].askp = z; ask[i*2].num = i; ask[i*2].nump = 1; } sort(ask+1, ask+1+2*m, cmp); int nowplace = 0; for (int i = 1; i <= m*2; ++i) { while (ask[i].place > nowplace) { nowplace++; add(1, nowplace); } if (ask[i].place) ans[ask[i].num][ask[i].nump] = askk(1, ask[i].askp); else ans[ask[i].num][ask[i].nump] = 0; } for (int i = 1; i <= m; ++i) printf("%d\n", (ans[i][1]+yu-ans[i][0]) % yu); return 0;}
Bzoj 3626 LCA