hdu3887 Counting Offspring(dfs序+树状数组)

来源:互联网 发布:mac模拟器电脑版 编辑:程序博客网 时间:2024/05/16 12:18

Counting Offspring

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2635    Accepted Submission(s): 907


Problem Description
You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.
 

Input
Multiple cases (no more than 10), for each case:
The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p.
Following n-1 lines, each line has two integers, representing an edge in this tree.
The input terminates with two zeros.
 

Output
For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.
 

Sample Input
15 77 107 17 97 37 410 1414 214 139 119 66 56 83 153 120 0
 

Sample Output
0 0 0 0 0 1 6 0 3 1 0 0 0 2 0
 

Author
bnugong
 

Source
2011 Multi-University Training Contest 5 - Host by BNU
 

Recommend
lcy   |   We have carefully selected several similar problems for you:  3450 1166 3030 1541 3743


 题解:统计树的每个节点下面的比它小的点的个数,首先利用dfs序找到每个点的子节点的区间,然后从小到大的查询就好了,每次查询完再把这个点插入进去;
#include<bits/stdc++.h>#define MAXN 100005using namespace std;int info[MAXN],lit[MAXN],l[MAXN],r[MAXN],tree[MAXN*2],vis[MAXN];vector<int> to,nxt;int cnt,n,p;void add(int a,int b){    to.push_back(b);    nxt.push_back(info[a]);    info[a]=to.size()-1;}void init(){    memset(info,-1,sizeof(info));    memset(lit,0,sizeof(lit));    to.clear();    nxt.clear();    memset(tree,0,sizeof(tree));    memset(vis,0,sizeof(vis));    cnt=1;}void dfs(int x){if(!vis[x]){vis[x]=1;l[x]=cnt++;}    for(int i=info[x];i!=-1;i=nxt[i])    {    if(!vis[to[i]])    dfs(to[i]);}r[x]=cnt++;}inline lowbit(int x){    return x&(-x);}void mod(int x){    for(int i=x;i<cnt;i+=lowbit(i))        tree[i]+=1;}int sum(int x){    int ans=0;    for(int i=x;i>0;i-=lowbit(i))        ans+=tree[i];    return ans;}int main(){    while(scanf("%d%d",&n,&p)!=EOF)    {    if(n==0&&p==0)    break;    init();        for(int i=0;i<n-1;i++)        {            int u,v;        scanf("%d%d",&u,&v);            add(u,v);            add(v,u);    }    dfs(p);    for(int i=1;i<=n;i++)    {        lit[i]=sum(r[i]-1)-sum(l[i]);       mod(l[i]);    }    for(int i=1;i<=n;i++)    {    if(i==n)    printf("%d\n",lit[i]);    else    printf("%d ",lit[i]);}      }    return 0;}


0 0