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;
}

 

posted @ 2019-06-28 11:17  lleozhang  Views(219)  Comments(0Edit  收藏  举报
levels of contents