将 \(\sum lca_{i, z}\) 的贡献拆分到每个 \(lca\) 到根的路径的结点,相当于统计 \(lca\) 到根的路径上点的点权和。
对于每个操作,可以依次将 \(l \cdots r\) 把到它们到根路径上结点加 \(1\),答案就是最后 \(z\) 到根路径的点权和,
可以通过处理出加入 \(1...l - 1\),\(1...r\) 的 \(z\) 到根路径的和,相减即为答案。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
#define fi first
#define se second
const int N = 1e5 + 10, inf = 0x3f3f3f3f, mod = 201314;
typedef pair <int, int> P;
typedef long long LL;
struct Edge {
int to, next;
} e[N];
vector <P> g[N];
int n, q, fa[N], h[N], cnt, tot;
int d[N], son[N], siz[N], st[N], top[N];
LL ans[N];
struct Tree {
LL v[N<<2]; int add[N<<2];
void down_(int o, int l, int r) {
int mid = (l + r)>>1, ls = o<<1, rs = o<<1|1;
v[ls] += (mid - l + 1)*add[o], v[rs] += (r - mid)*add[o];
add[ls] += add[o], add[rs] += add[o];
add[o] = 0;
}
void add_(int o, int l, int r, int x, int y, int k) {
if (x <= l && r <= y) {
v[o] += (r - l + 1)*k, add[o] += k;
return;
}
if (add[o]) down_(o, l, r);
int mid = (l + r)>>1;
if (x <= mid) add_(o<<1, l, mid, x, y, k);
if (mid < y) add_(o<<1|1, mid + 1, r, x, y, k);
v[o] = v[o<<1] + v[o<<1|1];
}
LL sum_(int o, int l, int r, int x, int y) {
if (x <= l && r <= y) return v[o];
if (add[o]) down_(o, l, r);
int mid = (l + r)>>1;
LL res = 0;
if (x <= mid) res += sum_(o<<1, l, mid, x, y);
if (mid < y) res += sum_(o<<1|1, mid + 1, r, x, y);
return res;
}
} T;
void add_(int u, int v) {
e[++cnt] = (Edge) {v, h[u]};
h[u] = cnt;
}
void dfs2_(int u, int topf) {
top[u] = topf, st[u] = ++tot;
if (son[u]) dfs2_(son[u], topf);
for (int v, i = h[u]; i; i = e[i].next) {
v = e[i].to;
if (v != son[u]) dfs2_(v, v);
}
}
void dfs1_(int u) {
d[u] = d[fa[u]] + 1, siz[u] = 1;
for (int v, i = h[u]; i; i = e[i].next) {
v = e[i].to;
dfs1_(v);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
void solve_() {
dfs1_(1), dfs2_(1, 1);
rep (i, 1, n) {
int u = i;
while (top[u] != 1) {
T.add_(1, 1, n, st[top[u]], st[u], 1);
u = fa[top[u]];
}
//cout<<"OK";
T.add_(1, 1, n, 1, st[u], 1);
rep (j, 0, (int) g[i].size() - 1) {
u = g[i][j].fi;
while (top[u] != 1) {
ans[abs(g[i][j].se)] += g[i][j].se/abs(g[i][j].se)*T.sum_(1, 1, n, st[top[u]], st[u]);
u = fa[top[u]];
}
ans[abs(g[i][j].se)] += g[i][j].se/abs(g[i][j].se)*T.sum_(1, 1, n, 1, st[u]);
}
}
}
int main() {
scanf("%d%d", &n, &q);
rep (i, 2, n) {
scanf("%d", &fa[i]), fa[i]++;
add_(fa[i], i);
}
for (int l, r, z, i = 1; i <= q; i++) {
scanf("%d%d%d", &l, &r, &z), l++, r++, z++;
g[l - 1].push_back(P(z, -i));
g[r].push_back(P(z, i));
}
solve_();
rep (i, 1, q) printf("%lld\n", ans[i]%mod);
return 0;
}