( ext{Solution})
发现一个事情
把 (i) 到根的路径都加 (1),然后让 (z) 往上跳,跳到第一个加了数的点就是他们的 (lca) 废话
如果把 (z) 到根的值加起来,那么就是 ( ext{dep[lca]}) 废话
如果把所有的 (i) 到根的路径都加一,再把 (z) 到根的值加起来,就是一个询问的答案!!
那我们就可以离线从大到小枚举 (i),加数,直接处理询问了
( ext{Code})
#include <cstdio>
#define LL long long
using namespace std;
const int N = 5e4 + 5;
const LL P = 201314;
int n, q, k, h[N], H[N], tot, Tot, ans[N];
struct edge{int nxt, to;}e[N];
struct node{int nxt, to, id, ty;}Q[N * 2];
int top[N], fa[N], dfn[N], siz[N], son[N], dfc;
void dfs1(int x)
{
siz[x] = 1;
for(int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
dfs1(v), siz[x] += siz[v];
if (siz[son[x]] < siz[v]) son[x] = v;
}
}
void dfs2(int x, int t)
{
top[x] = t, dfn[x] = ++dfc;
if (son[x]) dfs2(son[x], t);
for(int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == son[x]) continue;
dfs2(v, v);
}
}
#define ls (p << 1)
#define rs (ls | 1)
LL sum[N * 4], tag[N * 4];
inline void pushdown(int p, int l, int r)
{
if (!tag[p]) return;
int mid = (l + r) >> 1;
sum[ls] = (sum[ls] + tag[p] * (mid - l + 1) % P) % P, tag[ls] += tag[p];
sum[rs] = (sum[rs] + tag[p] * (r - mid) % P) % P, tag[rs] += tag[p];
tag[p] = 0;
}
void modify(int p, int l, int r, int tl, int tr, int v)
{
if (tl <= l && r <= tr)
{
sum[p] = (sum[p] + v * (r - l + 1)) % P, tag[p] += v;
return;
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if (tl <= mid) modify(ls, l, mid, tl, tr, v);
if (tr > mid) modify(rs, mid + 1, r, tl, tr, v);
sum[p] = (sum[ls] + sum[rs]) % P;
}
int query(int p, int l, int r, int tl, int tr)
{
if (tl <= l && r <= tr) return sum[p];
pushdown(p, l, r);
int mid = (l + r) >> 1, res = 0;
if (tl <= mid) res = query(ls, l, mid, tl, tr);
if (tr > mid) res += query(rs, mid + 1, r, tl, tr);
return res % P;
}
int main()
{
scanf("%d%d", &n, &q);
for(int i = 2; i <= n; i++) scanf("%d", &fa[i]), ++fa[i], e[++tot] = edge{h[fa[i]], i}, h[fa[i]] = tot;
dfs1(1), dfs2(1, 1);
for(int i = 1, x, y, z; i <= q; i++)
scanf("%d%d%d", &x, &y, &z), ++x, ++y, ++z,
Q[++Tot] = node{H[y], z, i, 1}, H[y] = Tot, Q[++Tot] = node{H[x - 1], z, i, -1}, H[x - 1] = Tot;
for(int i = 1, x, fx; i <= n; i++)
{
x = i;
for(; x; ) fx = top[x], modify(1, 1, n, dfn[fx], dfn[x], 1), x = fa[fx];
for(int j = H[i]; j; j = Q[j].nxt)
{
x = Q[j].to;
for(; x; )
fx = top[x], ans[Q[j].id] = (ans[Q[j].id] + Q[j].ty * query(1, 1, n, dfn[fx], dfn[x]) + P) % P, x = fa[fx];
}
}
for(int i = 1; i <= q; i++) printf("%d
", ans[i]);
}