按照深度从小大加入,就是一个很典型的熟练剖分加线段树实现路径修改、询问的模型
复杂度是 O(nlog2n)
最后一个点加个标记永久化、记忆化什么的卡一卡才能过…
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> par;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
template<class T> inline void rea(T &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
inline int rea(char *x,int L='a',int R='z'){
char c=nc(); x=0; int len=0;
for(;c>R||cfor(;c>=L&&c<=R;x[++len]=c,c=nc()); return len;
}
const int N=500010,P=1e9+7;
int n,rt,cnt,it,dpt[N],fa[N],p[N],b[N],son[N],size[N],top[N],q[N],G[N];
ll tot[N<<2];
int tag[N<<2];
struct edge{
int t,nx;
}E[N<<1];
inline void addedge(int x,int y){
E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
}
void dfs1(int x){
dpt[x]=dpt[fa[x]]+1; size[x]=1;
for(int i=G[x];i;i=E[i].nx){
dfs1(E[i].t); size[x]+=size[E[i].t];
if(size[E[i].t]>size[son[x]]) son[x]=E[i].t;
}
}
void dfs2(int x,int y){
top[x]=y; p[x]=++it; q[it]=x;
if(son[x]) dfs2(son[x],y);
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=son[x]) dfs2(E[i].t,E[i].t);
}
vector<int> v[N];
void Add(int g,int L,int R,int l,int r){
tot[g]+=r-l+1;
if(l==L && r==R) return tag[g]++,void();
int mid=L+R>>1;
if(r<=mid) Add(g<<1,L,mid,l,r);
else if(l>mid) Add(g<<1|1,mid+1,R,l,r);
else Add(g<<1,L,mid,l,mid),Add(g<<1|1,mid+1,R,mid+1,r);
}
ll Query(int g,int L,int R,int l,int r){
if(l==L && r==R) return tot[g];
int mid=L+R>>1;
if(r<=mid) return Query(g<<1,L,mid,l,r)+tag[g]*(r-l+1);
else if(l>mid) return Query(g<<1|1,mid+1,R,l,r)+tag[g]*(r-l+1);
else return Query(g<<1,L,mid,l,mid)+Query(g<<1|1,mid+1,R,mid+1,r)+tag[g]*(r-l+1);
}
inline void Add(int x){
while(x){
Add(1,1,n,p[top[x]],p[x]);
x=fa[top[x]];
}
}
int vis[N],iv;
ll ans[N],lst[N];
ll Query(int x){
if(!x) return 0;
if(vis[x]==iv) return lst[x];
vis[x]=iv;
return lst[x]=Query(1,1,n,p[top[x]],p[x])+Query(fa[top[x]]);
}
void PutAns(ll x){
if(x>=10) PutAns(x/10); putchar(x%10+'0');
}
int main(){
rea(n);
for(int i=1;i<=n;i++){
rea(fa[i]);
if(!fa[i]) rt=i;
else addedge(fa[i],i);
}
dfs1(rt);
dfs2(rt,rt);
for(int i=1;i<=n;i++) v[dpt[i]].push_back(i);
for(int i=1;i<=n;i++){
++iv;
for(int u : v[i])
Add(fa[u]);
for(int u : v[i])
ans[u]=Query(u);
}
for(int i=1;i<=n;i++) PutAns(ans[i]),putchar(' ');
return 0;
}