First of all the $ dep [LCA (i, z)] $ certainly can not be determined directly, put it into consideration, found $ dep [LCA (i, z)] $ $ I $ is equivalent to the point on the path to the root black after, $ z $ path to the root of the number of black dots. After By extension, $ (l, r, z) $ corresponding to all answer is $ l \ le i \ le r $ a $ i $, $ I $ to the value of +1 point on the path to the root weight $ z $ and root weights.
Then consider how to maintain this thing. + Summing path plus the path tree may be a cross-sectional, right after interrogation point range ordering may be inserted only once, and then use the data structure durable then the difference, the $ (l, r, z) $ into $ (1, r, z) - (1, l- 1, z) $ can be done $ O (nlog ^ 2n) $ a.
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int mod=201314; const int N=50005; char rB[1<<21],*rS,*rT,wB[1<<21]; int wp=-1; inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;} inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;} inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[15]; inline void wt(int x){ short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } pc(x|48); while(l>=0)pc(buf[l--]|48); pc('\n'); } int G[N],to[N],nxt[N],cnt=0,f[N],sz[N],dep[N],son[N],top[N],id[N],dfsc=0,sum[N<<2],addv[N<<2],n,r[N<<1]; struct query{ int r,z,s; }a[N<<1]; inline bool cmp(int x,int y){return a[x].r<a[y].r;} inline void add(int u,int v){ to[++cnt]=v;nxt[cnt]=G[u];G[u]=cnt; } void dfs1(int u,int fa){ int i,v,maxn=0; dep[u]=dep[f[u]=fa]+1; sz[u]=1; for(i=G[u];i;i=nxt[i]){ dfs1(v=to[i],u); sz[u]+=sz[v]; if(sz[v]>maxn)maxn=sz[son[u]=v]; } } void dfs2(int u,int topf){ int i,v; top[u]=topf; id[u]=++dfsc; if(!son[u])return; dfs2(son[u],topf); for(i=G[u];i;i=nxt[i])if((v=to[i])!=son[u])dfs2(v,v); } void add(int o,int L,int R,int x,int y){ if(x<=L&&y>=R){++addv[o];if((sum[o]+=R-L+1)>=mod)sum[o]-=mod;} else{ int lc=o<<1,rc=lc|1,M=L+R>>1; if(x<=M)add(lc,L,M,x,y); if(y>M)add(rc,M+1,R,x,y); sum[o]=(sum[lc]+sum[rc]+(ll)addv[o]*(R-L+1))%mod; } } int ask(int o,int L,int R,int x,int y){ if(x<=L&&y>=R)return sum[o]; int lc=o<<1,rc=lc|1,M=L+R>>1,ans=(ll)addv[o]*(min(y,R)-max(x,L)+1)%mod; if(x<=M&&(ans+=ask(lc,L,M,x,y))>=mod)ans-=mod; if(y>M&&(ans+=ask(rc,M+1,R,x,y))>=mod)ans-=mod; return ans; } inline void Add(int u){ while(u){ add(1,1,n,id[top[u]],id[u]); u=f[top[u]]; } } inline int Ask(int u){ int ans=0; while(u){ if((ans+=ask(1,1,n,id[top[u]],id[u]))>=mod)ans-=mod; u=f[top[u]]; } return ans; } int main(){ int q,i,j=1; n=rd();q=rd(); for(i=2;i<=n;++i)add(rd()+1,i); dfs1(1,0); dfs2(1,1); for(i=0;i<q;++i){a[i<<1|1].r=rd();a[i<<1].r=rd()+1;a[i<<1].z=a[i<<1|1].z=rd()+1;r[i<<1]=i<<1;r[i<<1|1]=i<<1|1;} sort(r,r+(q<<1),cmp); for(i=0;i<(q<<1);++i){ for(;j<=a[r[i]].r;++j)Add(j); a[r[i]].s=Ask(a[r[i]].z); } for(i=0;i<q;++i)wt((a[i<<1].s-a[i<<1|1].s+mod)%mod); flush(); return 0; }