#include<bits/stdc++.h>
using namespace std;
const int Maxn=5e4+1;
const int Mod=201314;
inline int read(){
int x=0;bool w=0;char ch=0;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return w?-x:x;
}
inline void write(int x){
if(x<0){x=-x;putchar('-');}
if(x>9)write(x/10);
putchar(x%10+48);
return ;
}
struct Tree{
int sum,lazy;
}tree[Maxn<<2];
int n,m;
int nxt[Maxn],head[Maxn],to[Maxn],cnt;
int father[Maxn],dep[Maxn],son[Maxn],seg[Maxn],siz[Maxn],top[Maxn];
//------------------------------------------------segment tree
void pushdown(int l,int r,int p){
int mid=(l+r)>>1;
tree[p<<1].sum+=tree[p].lazy*(mid-l+1);
tree[p<<1].sum%=Mod;
tree[p<<1].lazy+=tree[p].lazy;
tree[p<<1].lazy%=Mod;
tree[p<<1|1].sum+=tree[p].lazy*(r-mid);
tree[p<<1|1].sum%=Mod;
tree[p<<1|1].lazy+=tree[p].lazy;
tree[p<<1|1].lazy%=Mod;
tree[p].lazy=0;
return ;
}
void updata(int L,int R,int l,int r,int p){
if(L<=l&&r<=R){
tree[p].sum+=r-l+1;
tree[p].sum%=Mod;
tree[p].lazy+=1;
tree[p].lazy%=Mod;
return ;
}
pushdown(l,r,p);
int mid=(l+r)>>1;
if(L<=mid)updata(L,R,l,mid,p<<1);
if(R>=mid+1)updata(L,R,mid+1,r,p<<1|1);
tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%Mod;
return ;
}
int query(int L,int R,int l,int r,int p){
if(L<=l&&r<=R){
return tree[p].sum;
}
pushdown(l,r,p);
int mid=(l+r)>>1,res=0;
if(mid>=L)res+=query(L,R,l,mid,p<<1);
if(mid+1<=R)res+=query(L,R,mid+1,r,p<<1|1);
tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%Mod;
return res%Mod;
}
//------------------------------------------------Segment tree
//------------------------------------------------Tree chain partition
void add(int u,int v){
++cnt;
to[cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
return ;
}
void dfs1(int u){
siz[u]=1;
son[u]=Maxn-1;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==father[u])continue;
dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v]+1;
if(siz[v]>siz[son[u]]){
son[u]=v;
}
}
return ;
}
void dfs2(int u){
++seg[Maxn-1];
seg[u]=seg[Maxn-1];
if(son[u]==Maxn-1)return ;
top[son[u]]=top[u];
dfs2(son[u]);
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==father[u]||v==son[u])continue;
top[v]=v;
dfs2(v);
}
return ;
}
void updata_way(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
updata(seg[top[x]],seg[x],1,n,1);
x=father[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
updata(seg[x],seg[y],1,n,1);
return ;
}
int query_way(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
res+=query(seg[top[x]],seg[x],1,n,1);
res%=Mod;
x=father[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
res+=query(seg[x],seg[y],1,n,1);
return res%Mod;
}
//------------------------------------------------Tree chain partition
struct Prol{
int val,l,z,id;
}bleml[Maxn];
struct Pror{
int val,r,z,id;
}blemr[Maxn];
bool cmpl1(Prol a,Prol b){return a.l<b.l;}
bool cmpr1(Pror a,Pror b){return a.r<b.r;}
bool cmpl2(Prol a,Prol b){return a.id<b.id;}
bool cmpr2(Pror a,Pror b){return a.id<b.id;}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n-1;++i){
father[i]=read();
add(father[i],i);
}
dfs1(0);
dfs2(0);
for(int i=1;i<=m;++i){
bleml[i].l=read(),blemr[i].r=read();
bleml[i].z=blemr[i].z=read();
bleml[i].id=blemr[i].id=i;
}
sort(bleml+1,bleml+1+m,cmpl1);
sort(blemr+1,blemr+1+m,cmpr1);
int ln=1,rn=1;
for(int i=0;i<=n-1;++i){
updata_way(i,0);
while(bleml[ln].l-1==i){
bleml[ln].val=query_way(bleml[ln].z,0);
++ln;
}
while(blemr[rn].r==i){
blemr[rn].val=query_way(blemr[rn].z,0);
++rn;
}
}
sort(bleml+1,bleml+1+m,cmpl2);
sort(blemr+1,blemr+1+m,cmpr2);
for(int i=1;i<=m;++i){
write(((blemr[i].val-bleml[i].val)%Mod+Mod)%Mod);
putchar('\n');
}
return 0;
}