• cogs2039


    2039. 树的统计

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

    【题目描述】

    关于树的统计问题有多种多样的版本,这里你需要解决一个比较简单的问题:对于一棵包含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

    本来是要写一个CDQ分治的,可是树状数组太好写了!

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    int n;
    int sum[maxn];
    void add(int pos,int x)
    {
    	for(int i=pos;i<=n;i+=(-i)&i)sum[i]+=x;
    }
    int query(int pos)
    {
    	int ret=0;
    	for(int i=pos;i;i-=(-i)&i)ret+=sum[i];
    	return ret;
    }
    struct edge
    {
    	int u,v,nxt;
    }e[maxn<<1];
    int head[maxn],js;
    void addage(int u,int v)
    {
    	e[++js].u=u;e[js].v=v;
    	e[js].nxt=head[u];head[u]=js;
    }
    int l[maxn],r[maxn];
    int root,cnt;
    void dfs(int u,int fa)
    {
    	l[u]=++cnt;
    	for(int i=head[u];i;i=e[i].nxt)
    	{
    		int v=e[i].v;
    		if(v==fa)continue;
    		dfs(v,u);
    	}
    	r[u]=cnt;
    }
    int main()
    {
    	freopen("counttree.in","r",stdin);
        freopen("counttree.out","w",stdout);
    	scanf("%d",&n);
    	for(int x,i=1;i<=n;++i)
    	{
    		scanf("%d",&x);
    		if(x==0)
    		{
    			root=i;continue;
    		}
    		addage(i,x);addage(x,i);
    	}
    	dfs(root,0);
    	for(int i=1;i<=n;++i)
    	{
    		printf("%d ",query(r[i])-query(l[i]-1));
    		add(l[i],1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    【IDEA】(4)---很好用的DEBUG功能
    【IDEA】(3)---非常实用提高开发效率和水平的插件
    【IDEA】(2)---MAC代码模版
    【IDEA】(1)---MAC下常用快捷键
    Shell(2)—数组
    MySQL(12)---纪录一次left join一对多关系而引起的BUG
    MySQL(11)---约束
    Shell(1)---变量
    算法(2)---算法复杂度理论
    MySQL(10)---自定义函数
  • 原文地址:https://www.cnblogs.com/gryzy/p/15500774.html
Copyright © 2020-2023  润新知