首先这个$dep[LCA(i,z)]$肯定不能直接求,考虑把它转化,发现$dep[LCA(i,z)]$就等于把$i$到根的路径上的点涂黑后,$z$到根路径上黑点的个数。推而广之,$(l,r,z)$对应的答案就是对于所有$l\le i\le r$的$i$,将$i$到根的路径上的点权值+1后$z$到根的权值和。
然后考虑如何维护这个东西。路径加+路径求和可以树剖,对询问区间右端点排序后可以只插入一次,然后用可持久化数据结构然后差分,把$(l,r,z)$转化为$(1,r,z)-(1,l-1,z)$就可以做到$O(nlog^2n)$了。
#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; }