• 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;
    }
  • 相关阅读:
    可多开窗口,但是不能同一个窗口多标签 keyshot
    AI符号 和 3DS 实例 有点像
    maya 显示 着色
    不懂
    Rhino 图层
    C4D 怎么学了一个多月还什么都不会
    测试音乐文件 wav mp3 mid
    CAD转CDR之类的会断点怎么解决
    javascript
    react脚手架搭建
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11101654.html
Copyright © 2020-2023  润新知