COGS 2039. 树的统计

★★   输入文件:counttree.in   输出文件:counttree.out   简单对比
时间限制:1 s   内存限制:128 MB

【题目描述】

关于树的统计问题有多种多样的版本,这里你需要解决一个比较简单的问题:对于一棵包含N个节点的有根树,将所有点从1到N编号后,对于每一个节点v,统计出以v为根的子树中有多少个点的编号比v小。

 

【输入格式】

输入第一行包含一个整数N,以下N行每行包含一个整数,其中第i行的整数表示编号为i的节点的父亲节点的编号,根的父亲节点编号为0。

【输出格式】

输出包含N行,其中第i行给出编号为i的节点的统计结果。

【样例输入】

3
2
3
0

【样例输出】

0 1 2

【提示】

在此键入。

【来源】

20%的数据1<=n<=1000

100%的数据1<=n<=100000

 

树状数组

屠龙宝刀点击就送

#include <cstdio>
#define N 100005

struct Edge
{
    int next,to;
}edge[N];
int ans[N],root,tag[N],n,fa[N],head[N],cnt;
inline int lowbit(int x) {return x&(-x);}
inline int query(int x)
{
    int ans=0;
    for(;x;x-=lowbit(x)) ans+=tag[x];
    return ans;
}
inline void modify(int x)
{
    for(;x<=n;x+=lowbit(x)) tag[x]++;
}
void dfs(int x)
{
    ans[x]=-query(x-1);
    modify(x);
    for(int i=head[x];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v!=fa[x])
        dfs(v);
    }
    ans[x]+=query(x-1);
}
int main()
{
    freopen("counttree.in","r",stdin);freopen("counttree.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&fa[i]);
        if(!fa[i]) root=i;
        else
        {
            edge[++cnt].next=head[fa[i]];
            edge[cnt].to=i;
            head[fa[i]]=cnt;
        }
    }
    dfs(root);
    for(int i=1;i<=n;++i) printf("%d ",ans[i]);
    return 0;
}

 

posted @ 2017-08-22 21:26  杀猪状元  阅读(171)  评论(0编辑  收藏  举报