★★ 输入文件: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; }