CF860E
首先有个思想,就是逐层更新
然后考虑每次查询是查从某一点到根节点的树链上的信息,因此用树链剖分维护即可,处理每个点的对子树中节点的贡献可以区间修改(只需修改这一节点向上的树链即可),然后查询时区间查询,去掉不合法的部分即可
时间复杂度$O(nlog_{2}^{2}n)$,其实本题正解应当是$O(nlog_{2}n)$的,但是卡卡常能卡过
贴代码:
#include <cstdio> #include <algorithm> #include <queue> #define rint register unsigned int #define uint unsigned int #define ll unsigned long long #define rt1 rt<<1 #define rt2 (rt<<1)|1 using namespace std; struct Edge { uint nxt; uint to; }edge[500005]; struct Seg_tree { uint lazy; ll sum; }tree[2000005]; uint head[500005]; uint son[500005],siz[500005],ttop[500005],f[500005],nnum[500005],dep[500005],onum[500005],p[500005]; ll ret[500005]; uint cnt=1,RT,tot=0,maxdep; uint n; uint max(const uint &a,const uint &b) { return a>b?a:b; } bool cmp(uint a,uint b) { return dep[a]<dep[b]; } void add(const uint &l,const uint &r) { edge[cnt].nxt=head[l]; edge[cnt].to=r; head[l]=cnt++; } void dfs(uint x) { siz[x]=1,dep[x]=dep[f[x]]+1,maxdep=max(maxdep,dep[x]); for(rint i=head[x];i;i=edge[i].nxt) { uint to=edge[i].to; dfs(to); siz[x]+=siz[to],son[x]=(siz[to]>siz[son[x]])?to:son[x]; } } void redfs(uint x,uint topx) { ttop[x]=topx,nnum[x]=++tot,onum[tot]=x; if(son[x])redfs(son[x],topx); for(rint i=head[x];i;i=edge[i].nxt) { uint to=edge[i].to; if(to==son[x])continue; redfs(to,to); } } inline void pushdown(const uint &rt,const uint &l,const uint &r) { tree[rt1].lazy+=tree[rt].lazy; tree[rt2].lazy+=tree[rt].lazy; int mid=(l+r)>>1; tree[rt1].sum+=tree[rt].lazy*1ll*(mid-l+1); tree[rt2].sum+=tree[rt].lazy*1ll*(r-mid); tree[rt].lazy=0; } void update(uint rt,uint l,uint r,uint lq,uint rq,uint w) { if(l>=lq&&r<=rq) { tree[rt].lazy+=w; tree[rt].sum+=1ll*(r-l+1)*w; return; } if(tree[rt].lazy)pushdown(rt,l,r); uint mid=(l+r)>>1; if(lq<=mid)update(rt1,l,mid,lq,rq,w); if(rq>mid)update(rt2,mid+1,r,lq,rq,w); tree[rt].sum=tree[rt1].sum+tree[rt2].sum; } ll query(uint rt,uint l,uint r,uint lq,uint rq) { if(l>=lq&&r<=rq)return tree[rt].sum; if(tree[rt].lazy)pushdown(rt,l,r); uint mid=(l+r)>>1; ll s=0; if(lq<=mid)s+=query(rt1,l,mid,lq,rq); if(rq>mid)s+=query(rt2,mid+1,r,lq,rq); return s; } inline ll Query(uint x) { ll s=0; while(x)s+=query(1,1,n,nnum[ttop[x]],nnum[x]),x=f[ttop[x]]; return s; } inline void Update(uint x) { while(x)update(1,1,n,nnum[ttop[x]],nnum[x],1),x=f[ttop[x]]; } void print(ll x) { if(!x)return; print(x/10); putchar('0'+x%10); } inline void bfs() { uint las=1,llas=1; queue <int> Q; Q.push(RT); int deep=1; while(!Q.empty()) { queue <int> M; while(!Q.empty()&&dep[Q.front()]==deep) { int u=Q.front();Q.pop(); Update(u),M.push(u); for(rint i=head[u];i;i=edge[i].nxt)Q.push(edge[i].to); } while(!M.empty())ret[M.front()]=Query(f[M.front()]),M.pop(); ++deep; } for(rint i=1;i<=n;++i) { if(i==RT)putchar('0'); else print(ret[i]-dep[i]+1); putchar(' '); } } inline char Getchar() { static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline uint read() { uint f=1,x=0;char ch=Getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=Getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=Getchar();} return x*f; } int main() { n=read(); for(rint i=1;i<=n;++i) { f[i]=read(); if(f[i])add(f[i],i); else RT=i; } dfs(RT),redfs(RT,RT),bfs(); return 0; }