题目大意:给一棵树,q个询问,每次询问一个区间内的点与一个点的所有LCA的深度之和
很神的一道题啊...
首先对于每组询问,我们可以把这个区间内每个点到根的路径都+1,然后求被询问的点到根的路径和,就是这个询问的答案
然后我们可以把每组询问拆成两个,变成ans[R]-ans[L-1]
然后就可以离线,把0~n-1一个一个往里加,每次把它到根的路径+1,然后查询对应的那些询问就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
int to[N],nxt[N],pre[N],fa[N],cnt;
void ae(int ff,int tt)
{
cnt++;
to[cnt]=tt;
nxt[cnt]=pre[ff];
pre[ff]=cnt;
}
int d[N],zs[N],siz[N];
void build1(int x)
{
int maxn=0,maxb=0;
int i,j;
siz[x]=1;
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
d[j]=d[x]+1;
fa[j]=x;
build1(j);
siz[x]+=siz[j];
if(siz[j]>maxn)
{
maxn=siz[j];
maxb=j;
}
}
zs[x]=maxb;
}
int top[N],sit[N],fan[N],cn;
void make(int x,int tt)
{
cn++;sit[x]=cn;fan[cn]=x;
top[x]=tt;
int i,j;
if(zs[x]) make(zs[x],tt);
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
if(j==zs[x]) continue;
make(j,j);
}
}
struct ppp{int x,z,num,v;}b[N];
bool cmp(ppp x,ppp y){return x.x<y.x;}
int ans[N];
int l[N<<2],r[N<<2],sum[N<<2],t[N<<2];
void pup(int x){sum[x]=sum[x<<1]+sum[x<<1|1];}
void pud(int x)
{
sum[x<<1]+=(r[x<<1]-l[x<<1]+1)*t[x];
sum[x<<1|1]+=(r[x<<1|1]-l[x<<1|1]+1)*t[x];
t[x<<1]+=t[x];
t[x<<1|1]+=t[x];
t[x]=0;
}
void build(int now,int ll,int rr)
{
l[now]=ll;r[now]=rr;
if(ll==rr) return;
int mid=(ll+rr)>>1;
build(now<<1,ll,mid);
build(now<<1|1,mid+1,rr);
}
void change(int now,int ll,int rr)
{
if(l[now]==ll&&r[now]==rr)
{
t[now]++;
sum[now]+=r[now]-l[now]+1;
return;
}
if(t[now]) pud(now);
int mid=(l[now]+r[now])>>1;
if(rr<=mid) change(now<<1,ll,rr);
else if(ll>mid) change(now<<1|1,ll,rr);
else change(now<<1,ll,mid),change(now<<1|1,mid+1,rr);
pup(now);
}
int check(int now,int ll,int rr)
{
if(l[now]==ll&&r[now]==rr) return sum[now];
if(t[now]) pud(now);
int mid=(l[now]+r[now])>>1;
if(rr<=mid) return check(now<<1,ll,rr);
else if(ll>mid) return check(now<<1|1,ll,rr);
else return check(now<<1,ll,mid)+check(now<<1|1,mid+1,rr);
}
void changeit(int x)
{
while(x)
{
change(1,sit[top[x]],sit[x]);
x=fa[top[x]];
}
}
int checkit(int x)
{
int ans=0;
while(x)
{
ans+=check(1,sit[top[x]],sit[x]);
x=fa[top[x]];
}
return ans;
}
int mod=201314;
int main()
{
int n,q;
scanf("%d%d",&n,&q);
int i,j,x,y,z;
for(i=2;i<=n;i++)
{
scanf("%d",&x);
ae(x+1,i);
}
build1(1);
make(1,1);
for(i=1;i<=q;i++)
{
scanf("%d%d%d",&x,&y,&z);
x++;y++;z++;
b[2*i-1]=(ppp){x-1,z,i,-1};
b[2*i]=(ppp){y,z,i,1};
}
sort(b+1,b+2*q+1,cmp);
j=1;
while(b[j].x==0) j++;
build(1,1,n);
for(i=1;i<=n;i++)
{
changeit(i);
while(b[j].x==i)
{
ans[b[j].num]+=b[j].v*checkit(b[j].z);
j++;
}
}
for(i=1;i<=q;i++)
printf("%d\n",ans[i]%mod);
}