求两个点的LCA深度,我们可以染色一个点到根的路径,然后询问另一个点到根的路径。同样,求一堆点和另一个点的LCA深度之和,我们可以把这一堆点到根的路径打上标记然后对那个点到根的路径进行查询。这样的话,我们对原问题的每个询问差分,从
1
到
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=400010,p=201314;
struct query
{
int u,id,flag;
};
vector<query> v[maxn];
vector<int> son[maxn];
int fa[maxn],pref[maxn],dep[maxn],size[maxn],pos[maxn],top[maxn],
n,q,clo;
LL ans[maxn],sum[maxn],tag[maxn];
void dfs1(int u)
{
dep[u]=dep[fa[u]]+1;
size[u]=1;
for (vector<int>::iterator it=son[u].begin();it!=son[u].end();++it)
{
dfs1(*it);
if (!pref[u]||size[*it]>size[pref[u]]) pref[u]=*it;
size[u]+=size[*it];
}
}
void dfs2(int u)
{
pos[u]=++clo;
if (pref[u])
{
top[pref[u]]=top[u];
dfs2(pref[u]);
}
for (vector<int>::iterator it=son[u].begin();it!=son[u].end();++it)
if (*it!=pref[u])
{
top[*it]=*it;
dfs2(*it);
}
}
void down(int u,int L,int R)
{
if (tag[u])
{
sum[u]+=tag[u]*(R-L+1);
if (L<R)
{
tag[u*2]+=tag[u];
tag[u*2+1]+=tag[u];
}
tag[u]=0;
}
}
void up(int u,int L,int R)
{
down(u,L,R);
if (L<R)
{
int mid=(L+R)/2;
down(u*2,L,mid);
down(u*2+1,mid+1,R);
sum[u]=sum[u*2]+sum[u*2+1];
}
}
void modi(int u,int L,int R,int l,int r)
{
if (l<=L&&R<=r)
{
tag[u]++;
return;
}
down(u,L,R);
int mid=(L+R)/2;
if (l<=mid) modi(u*2,L,mid,l,r);
if (r>mid) modi(u*2+1,mid+1,R,l,r);
up(u,L,R);
}
int qry(int u,int L,int R,int l,int r)
{
down(u,L,R);
if (l<=L&&R<=r) return sum[u];
int mid=(L+R)/2,ret=0;
if (l<=mid) ret+=qry(u*2,L,mid,l,r);
if (r>mid) ret+=qry(u*2+1,mid+1,R,l,r);
return ret;
}
int main()
{
LL ret;
int l,r,u;
scanf("%d%d",&n,&q);
for (int i=2;i<=n;i++)
{
scanf("%d",&fa[i]);
fa[i]++;
son[fa[i]].push_back(i);
}
dfs1(1);
dfs2(1);
for (int i=1;i<=q;i++)
{
scanf("%d%d%d",&l,&r,&u);
v[l].push_back((query){u+1,i,-1});
v[r+1].push_back((query){u+1,i,1});
}
for (int i=1;i<=n;i++)
{
for (int j=i;j;j=fa[top[j]]) modi(1,1,n,pos[top[j]],pos[j]);
for (vector<query>::iterator it=v[i].begin();it!=v[i].end();++it)
{
ret=0;
for (int j=(*it).u;j;j=fa[top[j]]) ret+=qry(1,1,n,pos[top[j]],pos[j]);
ans[(*it).id]+=ret*(*it).flag;
}
}
for (int i=1;i<=q;i++) printf("%lld\n",ans[i]%p);
}