发现一次询问的答案就是把[l,r][l,r][l,r]所有点到根的路径+1+1+1后
zzz到根的路径权值和离线差分就完了
#includeusing namespace std;#define ll long long#define pb push_backconst int RLEN=1<<20|1;inline char gc(){ static char ibuf[RLEN],*ib,*ob; (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin)); return (ob==ib)?EOF:*ib++;}#define gc getcharinline int read(){ char ch=gc(); int res=0,f=1; while(!isdigit(ch))f^=ch=='-',ch=gc(); while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc(); return f?res:-res;}const int N=50005;const int mod=201314;inline int add(int a,int b){ return a+b>=mod?a+b-mod:a+b;}inline void Add(int &a,int b){ a=add(a,b);}inline int dec(int a,int b){ return a>=b?a-b:a-b+mod;}inline void Dec(int &a,int b){ a=dec(a,b);}inline int mul(int a,int b){ return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}int n,m;namespace Seg{ int tr[N<<2],tag[N<<2]; #define lc (u<<1) #define rc ((u<<1)|1) #define mid ((l+r)>>1) inline void pushup(int u){ tr[u]=add(tr[lc],tr[rc]); } inline void pushdown(int u,int l,int r){ if(!tag[u])return; Add(tr[lc],mul(mid-l+1,tag[u])); Add(tr[rc],mul(r-mid,tag[u])); Add(tag[lc],tag[u]); Add(tag[rc],tag[u]); tag[u]=0; } void update(int u,int l,int r,int st,int des,int k){ if(st<=l&&r<=des){ Add(tag[u],k),Add(tr[u],mul(r-l+1,k));return;} pushdown(u,l,r); if(st<=mid)update(lc,l,mid,st,des,k); if(mid siz[son[u]])son[u]=v; } } void dfs2(int u,int tp){ top[u]=tp,in[u]=++tot,idx[tot]=u; if(son[u])dfs2(son[u],tp); for(int e=adj[u];e;e=nxt[e]){ int v=to[e]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); } } inline int querypath(int u,int v){ int res=0; while(top[u]!=top[v]){ if(dep[top[u]] q[N];int ans[N],num;int main(){ n=read(),m=read(); for(int i=2;i<=n;i++){ int u=read()+1; addedge(u,i),addedge(i,u); } dfs1(1),dfs2(1,1); for(int i=1;i<=m;i++){ int l=read()+1,r=read()+1,p=read()+1; q[l-1].pb((qry){ p,-1,i}); q[r].pb((qry){ p,1,i}); } for(int i=1;i<=n;i++){ updatepath(1,i); for(int j=0;j