链剖,由于询问是询问一段区间内的所以我们建主席树,造两颗主席树,一个维护点的个数,一个维护点的深度和,对于每个点x,往根走,每走一条轻边到达轻边的父亲结点f,就在主席树上给f的点个数+1,深度和+f的深度(默认刚开始是走了一条轻边到达点x的)
查询的时候每走一条轻边到达一条重链上的结点x,求出重链上x和x以下有多少个点,再减去从来那条轻边底下来的点的个数,剩下这些点和询问点的lca都是x,用点的个数*x的深度记入答案,对于重链上x以上的点,LCA就是那些点,求深度和加到答案里,然后走到重链顶端的轻边上边并更新从轻边带上来的点数(默认刚开始是走了一条轻边到达询问点)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<ctime>
#include<vector>
#include<stack>
#include<set>
#include<bitset>
#include<map>
#include<queue>
using namespace std;
#define MAXN 50010
#define MAXM 10000010
#define MOD 201314
#define INF 1000000000
#define eps 1e-8
#define ll long long
struct vec{
int to;
int fro;
};
vec mp[MAXN*2];
int tai[MAXN],cnt;
int siz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],dfn[MAXN],ndf[MAXN],tp[MAXN],lw[MAXN],tim;
int n,m,q;
int srt[MAXN],drt[MAXN];
int v[MAXM],Son[MAXM][2];
int tot;
int now;
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
inline void bde(int x,int y){
be(x,y);
be(y,x);
}
void dfs1(int x){
int i,y;
siz[x]=1;
dep[x]=dep[fa[x]]+1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(!siz[y]){
fa[y]=x;
dfs1(y);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]){
son[x]=y;
}
}
}
}
void dfs2(int x,int z){
int i,y;
tp[x]=z;
lw[z]=x;
dfn[x]=++tim;
ndf[tim]=x;
if(son[x]){
dfs2(son[x],z);
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(!dfn[y]){
dfs2(y,y);
}
}
}
}
void change(int &x,int xx,int y,int z,int p,int cv){
x=++tot;
v[x]=(v[xx]+cv)%MOD;
memcpy(Son[x],Son[xx],sizeof(Son[x]));
if(y==z){
return ;
}
int mid=y+z>>1;
if(p<=mid){
change(Son[x][0],Son[xx][0],y,mid,p,cv);
}else{
change(Son[x][1],Son[xx][1],mid+1,z,p,cv);
}
}
void tochange(int x){
while(x){
change(srt[now],srt[now],1,n,dfn[x],1);
change(drt[now],drt[now],1,n,dfn[x],dep[x]);
x=fa[tp[x]];
}
}
int ask(int x,int xx,int y,int z,int l,int r){
if(l>r||!l){
return 0;
}
if(y==l&&z==r){
return (v[xx]-v[x]+MOD)%MOD;
}
int mid=y+z>>1;
if(r<=mid){
return ask(Son[x][0],Son[xx][0],y,mid,l,r);
}else if(l>mid){
return ask(Son[x][1],Son[xx][1],mid+1,z,l,r);
}else{
return (ask(Son[x][0],Son[xx][0],y,mid,l,mid)+ask(Son[x][1],Son[xx][1],mid+1,z,mid+1,r))%MOD;
}
}
int toask(int l,int r,int x){
int lu=0;
int re=0;
while(x){
(re+=(ll)ask(srt[l-1],srt[r],1,n,dfn[son[x]],dfn[lw[tp[x]]])*dep[x]%MOD)%=MOD;
(re+=(ll)(ask(srt[l-1],srt[r],1,n,dfn[x],dfn[x])-lu)*dep[x]%MOD)%=MOD;
(re+=ask(drt[l-1],drt[r],1,n,dfn[tp[x]],dfn[fa[x]]))%=MOD;
lu=ask(srt[l-1],srt[r],1,n,dfn[tp[x]],dfn[lw[tp[x]]]);
x=fa[tp[x]];
}
return re;
}
int main(){
int i,x,y,l,r;
scanf("%d%d",&n,&m);
for(i=2;i<=n;i++){
scanf("%d",&x);
x++;
bde(x,i);
}
dfs1(1);
dfs2(1,1);
for(now=1;now<=n;now++){
srt[now]=srt[now-1];
drt[now]=drt[now-1];
tochange(now);
}
while(m--){
scanf("%d%d%d",&l,&r,&x);
l++;
r++;
x++;
printf("%d\n",toask(l,r,x));
}
return 0;
}
/*
7 100
0 0 1 1 2 2
*/