正题
P4211
题目大意
给你一棵树,有m次询问,每次询问要回答∑i=lrdep[lca(x,i)]\sum_{i=l}^rdep[lca(x,i)]∑i=lrdep[lca(x,i)]
解题思路
把用差分把问题分开,离线做
考虑树链剖分,对于每个点维护轻儿子的贡献,即轻子树的大小乘dep[x]
每次查询对于重链中到达的第一个点,计算子树大小再减去上个子树大小(计算过的),然后乘上dep[x],重链上其他点直接贡献求和
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define wyc 201314
#define N 50050
using namespace std;
ll n,m,x,y,z,w,qw,ww,tot,h[N],hs[N],sz[N],fa[N],ans[N],dep[N],top[N],dfn[N],low[N];
struct rec
{ll to,nx;
}e[N];
struct node
{node(ll qq=0,ll xx=0,ll yy=0,ll gg=0){q=qq,x=xx,y=yy,g=gg;}ll q,x,y,g;
}q[N<<1];
void add(ll x,ll y)
{e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return;
}
void dfs1(ll x)
{sz[x]=1;for(ll i=h[x];i;i=e[i].nx){ll y=e[i].to;dep[y]=dep[x]+1;fa[y]=x;dfs1(y);sz[x]+=sz[y];if(sz[y]>sz[hs[x]])hs[x]=y;}return;
}
void dfs2(ll x,ll anc)
{dfn[x]=++w;top[x]=anc;if(hs[x])dfs2(hs[x],anc);for(ll i=h[x];i;i=e[i].nx){ll y=e[i].to;if(y!=hs[x])dfs2(y,y);}low[x]=w;return;
}
bool cmp(node a,node b)
{return a.x<b.x;
}
struct Tree
{#define ls x*2#define rs x*2+1ll s[N<<5],sz[N<<5];void push_up(ll x){s[x]=s[ls]+s[rs];sz[x]=sz[ls]+sz[rs];return;}void add(ll x,ll l,ll r,ll y,ll z,ll zz){if(l==r){s[x]+=z;sz[x]+=zz;return;}ll mid=l+r>>1;if(y<=mid)add(ls,l,mid,y,z,zz);else add(rs,mid+1,r,y,z,zz);push_up(x);return;}ll ask(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return s[x];ll mid=L+R>>1;if(r<=mid)return ask(ls,L,mid,l,r);else if(l>mid)return ask(rs,mid+1,R,l,r);else return ask(ls,L,mid,l,mid)+ask(rs,mid+1,R,mid+1,r);}ll asksz(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return sz[x];ll mid=L+R>>1;if(r<=mid)return asksz(ls,L,mid,l,r);else if(l>mid)return asksz(rs,mid+1,R,l,r);else return asksz(ls,L,mid,l,mid)+asksz(rs,mid+1,R,mid+1,r);}
}T;
void add(ll x)
{T.add(1,1,n,dfn[x],0,1);while(x){T.add(1,1,n,dfn[x],dep[x],0);x=fa[top[x]];}return;
}
ll ask(ll x)
{ll lst=0,sum=0;while(x){sum+=(T.asksz(1,1,n,dfn[x],low[x])-lst)*dep[x];//子树内的点都到该点if(top[x]!=x)sum+=T.ask(1,1,n,dfn[top[x]],dfn[fa[x]]);//直接计算贡献lst=T.asksz(1,1,n,dfn[top[x]],low[top[x]]);//上一个子树的大小x=fa[top[x]];}return sum;
}
int main()
{scanf("%lld%lld",&n,&m);for(ll i=2;i<=n;++i){scanf("%lld",&x);x++;add(x,i);}dep[1]=1;dfs1(1);dfs2(1,1);for(ll i=1;i<=m;++i){scanf("%lld%lld%lld",&x,&y,&z);x++,y++,z++;q[++qw]=node(i,x-1,z,-1);q[++qw]=node(i,y,z,1);}sort(q+1,q+1+qw,cmp);ww=1;while(ww<=qw&&q[ww].x<=0)ww++;for(ll i=1;i<=n;++i){add(i);while(ww<=qw&&q[ww].x<=i)ans[q[ww].q]+=ask(q[ww].y)*q[ww].g,ww++;}for(ll i=1;i<=m;++i)printf("%lld\n",ans[i]%wyc);return 0;
}